// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "common/text/macro_definition.h"

#include <iterator>
#include <map>
#include <string>
#include <vector>

#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "common/text/token_info.h"
#include "common/util/container_util.h"

namespace verible {

using container::FindOrNull;

bool MacroDefinition::AppendParameter(const MacroParameterInfo& param_info) {
  is_callable_ = true;
  // Record position of this parameter.
  const bool inserted = parameter_positions_
                            .insert({std::string(param_info.name.text()),
                                     parameter_info_array_.size()})
                            .second;
  parameter_info_array_.push_back(param_info);
  return inserted;
}

absl::Status MacroDefinition::PopulateSubstitutionMap(
    const std::vector<TokenInfo>& macro_call_args,
    substitution_map_type* arg_map) const {
  if (macro_call_args.size() != parameter_info_array_.size()) {
    return absl::InvalidArgumentError(
        absl::StrCat("Error calling macro ", name_.text(), " with ",
                     macro_call_args.size(), " arguments, but definition has ",
                     parameter_info_array_.size(), " formal parameters."));
    // TODO(fangism): also allow one blank argument when number of formals is 0.
  }
  auto actuals_iter = macro_call_args.begin();
  const auto actuals_end = macro_call_args.end();
  auto formals_iter = parameter_info_array_.begin();
  for (; actuals_iter != actuals_end; ++actuals_iter, ++formals_iter) {
    auto& replacement_text = (*arg_map)[formals_iter->name.text()];
    if (!actuals_iter->text().empty()) {
      // Actual text is provided.
      replacement_text = *actuals_iter;
    } else if (!formals_iter->default_value.text().empty()) {
      // Use default parameter value.
      replacement_text = formals_iter->default_value;
    }
    // else leave blank as empty string.
  }
  return absl::OkStatus();
}

const TokenInfo& MacroDefinition::SubstituteText(
    const substitution_map_type& substitution_map, const TokenInfo& token_info,
    int actual_token_enum) {
  if (actual_token_enum == 0 ||
      (actual_token_enum == token_info.token_enum())) {
    const auto* replacement = FindOrNull(substitution_map, token_info.text());
    if (replacement) {
      // Substitute formal parameter for actual text.
      return *replacement;
    }
  }
  // Didn't match enum type nor find map entry, so don't substitute.
  return token_info;
}

}  // namespace verible
