/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 "executor/contract/manager/contract_manager.h"

#include "eEVM/processor.h"
#include "executor/contract/manager/address_manager.h"
#include "glog/logging.h"

namespace resdb {
namespace contract {

void AppendArgToInput(std::vector<uint8_t>& code, const uint256_t& arg) {
  const auto pre_size = code.size();
  code.resize(pre_size + 32u);
  eevm::to_big_endian(arg, code.data() + pre_size);
}

void AppendArgToInput(std::vector<uint8_t>& code, const std::string& arg) {
  AppendArgToInput(code, eevm::to_uint256(arg));
}

ContractManager::ContractManager(Storage* storage) {
  gs_ = std::make_unique<GlobalState>(storage);
}

std::string ContractManager::GetFuncAddress(const Address& contract_address,
                                            const std::string& func_name) {
  return func_address_[contract_address][func_name];
}

void ContractManager::SetFuncAddress(const Address& contract_address,
                                     const FuncInfo& func) {
  func_address_[contract_address][func.func_name()] = func.hash();
}

Address ContractManager::DeployContract(const Address& owner_address,
                                        const DeployInfo& deploy_info) {
  const auto contract_address =
      AddressManager::CreateContractAddress(owner_address);

  auto contract_constructor = eevm::to_bytes(deploy_info.contract_bin());
  for (const std::string& param : deploy_info.init_param()) {
    AppendArgToInput(contract_constructor, param);
  }

  try {
    auto contract = gs_->create(contract_address, 0u, contract_constructor);

    auto result = Execute(owner_address, contract_address, {});
    if (result.ok()) {
      // set the initialized class context code.
      contract.acc.set_code(std::move(*result));

      for (const auto& info : deploy_info.func_info()) {
        SetFuncAddress(contract_address, info);
      }
      return contract.acc.get_address();
    } else {
      gs_->remove(contract_address);
      return 0;
    }
  } catch (...) {
    LOG(ERROR) << "Deploy throw expection";
    return 0;
  }
}

absl::StatusOr<eevm::AccountState> ContractManager::GetContract(
    const Address& address) {
  if (!gs_->Exists(address)) {
    return absl::InvalidArgumentError("Contract not exist.");
  }

  return gs_->get(address);
}

absl::StatusOr<std::string> ContractManager::ExecContract(
    const Address& caller_address, const Address& contract_address,
    const Params& func_param) {
  std::string func_addr =
      GetFuncAddress(contract_address, func_param.func_name());
  if (func_addr.empty()) {
    LOG(ERROR) << "no fouction:" << func_param.func_name();
    return absl::InvalidArgumentError("Func not exist.");
  }

  std::vector<uint8_t> inputs = eevm::to_bytes(func_addr);
  for (const std::string& param : func_param.param()) {
    AppendArgToInput(inputs, param);
  }

  auto result = Execute(caller_address, contract_address, inputs);

  if (result.ok()) {
    return eevm::to_hex_string(*result);
  }
  return result.status();
}

absl::StatusOr<std::vector<uint8_t>> ContractManager::Execute(
    const Address& caller_address, const Address& contract_address,
    const std::vector<uint8_t>& input) {
  // Ignore any logs produced by this transaction
  eevm::NullLogHandler ignore;
  eevm::Transaction tx(caller_address, ignore);

  // Record a trace to aid debugging
  eevm::Trace tr;
  eevm::Processor p(*gs_);

  // Run the transaction
  try {
    const auto exec_result =
        p.run(tx, caller_address, gs_->get(contract_address), input, 0u, &tr);

    if (exec_result.er != eevm::ExitReason::returned) {
      // Print the trace if nothing was returned
      if (exec_result.er == eevm::ExitReason::threw) {
        return absl::InternalError(
            fmt::format("Execution error: {}", exec_result.exmsg));
      }
      return absl::InternalError("Deployment did not return");
    }
    return exec_result.output;
  } catch (...) {
    return absl::InternalError(fmt::format("Execution error:"));
  }
}

std::string ContractManager::GetBalance(const Address& account) {
  return gs_->GetBalance(account);
}

int ContractManager::SetBalance(const Address& account,
                                const uint256_t& balance) {
  return gs_->SetBalance(account, balance);
}

}  // namespace contract
}  // namespace resdb
