
#ifndef PORYGONLANG_BOUNDSCOPE_HPP
#define PORYGONLANG_BOUNDSCOPE_HPP

#include <string>
#include <map>
#include <unordered_map>
#include <vector>
#include <memory>
#include "BoundVariable.hpp"
#include "BoundVariableKey.hpp"
#include "VariableAssigmentResult.hpp"
#include "../../Utilities/HashedString.hpp"

using namespace std;

namespace Porygon::Binder {
    class BoundScope {
        map<Utilities::HashedString, BoundVariable *> *_tableScope;
        unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>> * _tableVariableTypes;
        vector<map<Utilities::HashedString, BoundVariable *> *> _localScope;
        int _currentScope;
        int _lastCreatedScope;
    public:
        explicit BoundScope(map<Utilities::HashedString, BoundVariable *> *tableScope,
                            unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>* tableVariableTypes);

        ~BoundScope();

        void GoInnerScope();

        void GoOuterScope();

        int Exists(const Utilities::HashedString& key);

        BoundVariable *GetVariable(uint32_t scope, const Utilities::HashedString& identifier);

        VariableAssignment CreateExplicitLocal(const Utilities::HashedString& identifier, std::shared_ptr<const ScriptType> type);

        VariableAssignment AssignVariable(const Utilities::HashedString& identifier, const std::shared_ptr<const ScriptType> &type);

        inline size_t GetLocalVariableCount() {
            return _localScope.size();
        }
    };
}


#endif //PORYGONLANG_BOUNDSCOPE_HPP
