
#include "EvaluationScope.hpp"
#include "../../StandardLibraries/StaticScope.hpp"
#include <memory>

namespace Porygon::Evaluation {
    EvaluationScope::EvaluationScope(map<Utilities::HashedString, EvalValuePointer> *scriptVariables)
            : _scriptScope(scriptVariables),
              _localScope(map<uint64_t, EvalValuePointer>()) {
    }

    void EvaluationScope::CreateVariable(const BoundVariableKey *key, EvalValuePointer value) {
        if (key->GetScopeId() == 0) {
            _scriptScope->at(*key->GetIdentifier()).ClearAssign(value.Take());
        } else {
            auto val = value.Clone();
            auto insert = _localScope.insert({key->GetHash(), val});
            if (!insert.second) {
                _localScope[key->GetHash()].ClearAssign(value.Take());
            }
        }
    }

    void EvaluationScope::SetVariable(const BoundVariableKey *key, EvalValuePointer value) {
        if (key->GetScopeId() == 0) {
            _scriptScope->at(*key->GetIdentifier()).ClearAssign(value.Take());
        } else {
            _localScope[key->GetHash()].ClearAssign(value.Take());
        }
    }

    EvalValuePointer EvaluationScope::GetVariable(const BoundVariableKey *key) {
        auto scopeId = key -> GetScopeId();
        if (scopeId== 0) {
            return _scriptScope->at(*key->GetIdentifier())->Clone();
        } else if(scopeId == -2){
            return StandardLibraries::StaticScope::GetVariable(*key->GetIdentifier()).Clone();
        } else {
            return _localScope[key->GetHash()]->Clone();
        }
    }
}