/**
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
 * CANN Open Software License Agreement Version 2.0 (the "License").
 * Please refer to the License for details. You may not use this file except in compliance with the License.
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
 * See LICENSE in the root of the software repository for the full text of the License.
 */

#include "array_utils.h"
#include <map>
#include <vector>
#include <set>

namespace acl {
namespace array_utils {
bool IsAllTensorEmpty(const int32_t size, const aclTensorDesc *const *const arr) {
  if (size == 0) {
    return false;
  }

  for (int32_t idx = 0; idx < size; ++idx) {
    bool flag = false;
    for (size_t idy = 0U; idy < arr[idx]->dims.size(); ++idy) {
      if (arr[idx]->dims[idy] == 0) {
        flag = true;
        break;
      }
    }

    if (!flag) {
      return false;
    }
  }

  return true;
}

bool IsAllTensorEmpty(const int32_t size, const aclDataBuffer *const *const arr) {
  if (size == 0) {
    return false;
  }

  for (int32_t idx = 0; idx < size; ++idx) {
    if (arr[idx]->length > 0U) {
      return false;
    }
  }

  return true;
}

bool GetDynamicInputIndex(const int32_t size, const aclTensorDesc *const *const arr, DynamicInputIndexPair &indexPair) {
  indexPair.first.clear();
  indexPair.second.clear();
  auto &startVec = indexPair.first;
  auto &endVec = indexPair.second;
  if (size == 0) {
    return true;
  }

  std::set<std::string> attrNameSet;
  int32_t start = -1;
  int32_t ended = -1;
  std::string lastName;
  for (int32_t i = 0; i < size; ++i) {
    const std::string curName = arr[i]->dynamicInputName;
    if ((curName.size() == 0U) && (lastName.size() == 0U)) {
      continue;
    }

    if (curName != lastName) {
      // current name exist before
      if (attrNameSet.find(curName) != attrNameSet.end()) {
        ACL_LOG_ERROR("[Check][DynamicInputName]DynamicInputName[%s] is duplicated to other input name",
                      curName.c_str());
        acl::AclErrorLogManager::ReportInputError(
            acl::INVALID_PARAM_MSG, std::vector<const char *>({"param", "value", "reason"}),
            std::vector<const char *>(
                {"dynamicInputName", curName.c_str(), "DynamicInputName is duplicated to other input name."}));
        return false;
      }
      // valid attr name
      if (lastName.size() > 0U) {
        startVec.emplace_back(start);
        endVec.emplace_back(ended);
        (void)attrNameSet.insert(lastName);
      }

      if (curName.size() > 0U) {
        start = i;
      }
    }
    ended = i;           // refresh ended index
    lastName = curName;  // refresh lastName
  }

  if (lastName.size() > 0U) {
    startVec.emplace_back(start);
    endVec.emplace_back(ended);
  }

  return true;
}

aclError CheckDataBufferArry(const int32_t size, const aclDataBuffer *const *const arr) {
  if (size == 0) {
    return ACL_SUCCESS;
  }

  ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(arr);
  for (int32_t idx = 0; idx < size; ++idx) {
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(arr[idx]);
    if ((arr[idx]->data == nullptr) && (arr[idx]->length > 0U)) {
      ACL_LOG_ERROR("[Check][data]data of element at index[%d] while size is larger than 0", idx);
      const std::string errMsg = acl::AclErrorLogManager::FormatStr(
          "data of element at index[%d]"
          "while size is larger than 0",
          idx);
      acl::AclErrorLogManager::ReportInputError(acl::INVALID_PARAM_MSG,
                                                std::vector<const char *>({"param", "value", "reason"}),
                                                std::vector<const char *>({"data", "nullptr", errMsg.c_str()}));
      return ACL_ERROR_INVALID_PARAM;
    }
  }

  return ACL_SUCCESS;
}

aclError IsHostMemTensorDesc(const int32_t size, const aclTensorDesc *const *const arr) {
  if (size == 0) {
    return ACL_SUCCESS;
  }
  ACL_REQUIRES_NOT_NULL(arr);
  for (int32_t idx = 0; idx < size; ++idx) {
    if ((!arr[idx]->IsConstTensor()) && (arr[idx]->IsHostMemTensor())) {
      ACL_LOG_INNER_ERROR("[Check][HostMemTensorDesc]PlaceMent of element at index %d is hostMem", idx);
      ;
      return ACL_ERROR_INVALID_PARAM;
    }
  }

  return ACL_SUCCESS;
}
}  // namespace array_utils
}  // namespace acl