// ir/GlobalValue.cpp
#include "ir/IR.h"
#include <stdexcept>

namespace ir {

GlobalValue::GlobalValue(std::shared_ptr<Type> ty, std::string name)
    : User(std::move(ty), std::move(name)) {}

void GlobalValue::SetInitializer(ConstantValue* init) {
  if (!init) {
    throw std::runtime_error("GlobalValue::SetInitializer: init is null");
  }
  
  // 获取实际的值类型（用于类型检查）
  std::shared_ptr<Type> value_type;
  
  // 如果当前类型是指针，获取指向的值类型
  if (GetType()->IsPtrInt32()) {
    value_type = Type::GetInt32Type();
  } else if (GetType()->IsPtrFloat()) {
    value_type = Type::GetFloatType();
  } else if (GetType()->IsPtrInt1()) {
    value_type = Type::GetInt1Type();
  } else {
    // 非指针类型：直接使用当前类型
    value_type = GetType();
  }
  
  // 类型检查
  bool type_match = false;
  
  // 检查标量类型
  if (value_type->IsInt32() && init->GetType()->IsInt32()) {
    type_match = true;
  } else if (value_type->IsFloat() && init->GetType()->IsFloat()) {
    type_match = true;
  } else if (value_type->IsInt1() && init->GetType()->IsInt1()) {
    type_match = true;
  }
  // 检查数组类型：允许用单个标量初始化整个数组
  else if (value_type->IsArray()) {
    auto* array_ty = static_cast<ArrayType*>(value_type.get());
    auto* elem_type = array_ty->GetElementType().get();
    
    if (elem_type->IsInt32() && init->GetType()->IsInt32()) {
      type_match = true;
    } else if (elem_type->IsFloat() && init->GetType()->IsFloat()) {
      type_match = true;
    }
  }
  
  if (!type_match) {
    throw std::runtime_error("GlobalValue::SetInitializer: type mismatch");
  }
  
  initializer_.clear();
  initializer_.push_back(init);
}

void GlobalValue::SetInitializer(const std::vector<ConstantValue*>& init) {
  if (init.empty()) {
    return;
  }
  
  // 获取实际的值类型
  std::shared_ptr<Type> value_type;
  
  if (GetType()->IsPtrInt32()) {
    value_type = Type::GetInt32Type();
  } else if (GetType()->IsPtrFloat()) {
    value_type = Type::GetFloatType();
  } else if (GetType()->IsPtrInt1()) {
    value_type = Type::GetInt1Type();
  } else {
    value_type = GetType();
  }
  
  // 检查类型
  if (value_type->IsArray()) {
    auto* array_ty = static_cast<ArrayType*>(value_type.get());
    size_t array_size = array_ty->GetElementCount();
    
    if (init.size() > array_size) {
      throw std::runtime_error("GlobalValue::SetInitializer: too many initializers");
    }
    
    // 检查每个初始化值的类型
    auto* elem_type = array_ty->GetElementType().get();
    for (auto* elem : init) {
      bool elem_match = false;
      if (elem_type->IsInt32() && elem->GetType()->IsInt32()) {
        elem_match = true;
      } else if (elem_type->IsFloat() && elem->GetType()->IsFloat()) {
        elem_match = true;
      }
      
      if (!elem_match) {
        throw std::runtime_error("GlobalValue::SetInitializer: element type mismatch");
      }
    }
  } 
  else if (value_type->IsInt32() || value_type->IsFloat() || value_type->IsInt1()) {
    if (init.size() != 1) {
      throw std::runtime_error("GlobalValue::SetInitializer: scalar requires exactly one initializer");
    }
    
    if ((value_type->IsInt32() && !init[0]->GetType()->IsInt32()) ||
        (value_type->IsFloat() && !init[0]->GetType()->IsFloat()) ||
        (value_type->IsInt1() && !init[0]->GetType()->IsInt1())) {
      throw std::runtime_error("GlobalValue::SetInitializer: type mismatch");
    }
  } 
  else {
    throw std::runtime_error("GlobalValue::SetInitializer: unsupported type");
  }
  
  initializer_ = init;
}

}  // namespace ir