#include "..\script_component.hpp"

/*
 * Author: IDSolutions
 * Initializes the org store.
 *
 * Arguments:
 * None
 *
 * Return Value:
 * None
 *
 * Examples:
 * call forge_server_org_fnc_initOrgStore
 *
 * Public: Yes
 */

#pragma hemtt ignore_variables ["_self"]
GVAR(OrgStore) = createHashMapObject [[
    ["#type", "IOrgStore"],
    ["#create", {
        GVAR(IndexRegistry) = createHashMap;
        GVAR(OrgRegistry) = createHashMap;

        private _hashMap = createHashMap;
        _hashMap set ["id", "default"];
        _hashMap set ["owner", "server"];
        _hashMap set ["name", "Forge Dynamics"];
        _hashMap set ["funds", 200000];
        _hashMap set ["reputation", 0];

        private _json = _self call ["toJSON", [_hashMap]];
        ["org:create", ["default", _json]] call EFUNC(extension,extCall);

        ["INFO", "Org Store Initialized!", nil, nil] call EFUNC(common,log);
    }],
    ["init", {
        params [["_uid", "", [""]], ["_defaultOrg", createHashMap, [createHashMap]]];

        private _actor = EGVAR(actor,ActorRegistry) get _uid;
        private _orgID = _actor get "organization";

        ["org:exists", [_orgID]] call EFUNC(extension,extCall) params ["_result", "_isSuccess"];

        private _exists = _result == "true";
        private _player = [_uid] call EFUNC(common,getPlayer);

        if !(_exists) exitWith {
            _self call ["default", [_uid, (name _player)]];
            ["WARNING", format ["No existing org found for %1, using default org.", _uid], nil, nil] call EFUNC(common,log);
        };

        private _regEntry = createHashMapFromArray [["orgID", _orgID]];
        GVAR(IndexRegistry) set [_uid, _regEntry];

        private _organization = _self call ["fetch", [_uid]];
        private _members = _self call ["fetchMembers", [_uid]];
        // private _assets = _self call ["fetchAssets", [_uid]];

        private _finalOrg = GVAR(OrgRegistry) getOrDefault [_orgID, _organization];
        _finalOrg set ["members", _members];
        // _finalOrg set ["assets", _assets];

        GVAR(OrgRegistry) set [_orgID, _finalOrg, true];
        [CRPC(org,responseInitOrg), [_finalOrg], _player] call CFUNC(targetEvent);

        ["INFO", format ["Found org for %1", _uid], nil, nil] call EFUNC(common,log);
        _finalOrg
    }],
    ["default", {
        params [["_uid", "", [""]], ["_name", "", [""]]];

        private _assets = createHashMap;
        private _members = createHashMap;
        private _member = createHashMapFromArray [["uid", _uid], ["name", _name]];

        private _regEntry = createHashMapFromArray [["orgID", "default"]];
        GVAR(IndexRegistry) set [_uid, _regEntry];

        private _organization = _self call ["fetch", ["default"]];
        _members set [_uid, _member];

        private _finalOrg = GVAR(OrgRegistry) getOrDefault ["default", _organization];
        _finalOrg set ["members", _members];
        _finalOrg set ["assets", _assets];

        GVAR(OrgRegistry) set ["default", _finalOrg];

        private _player = [_uid] call EFUNC(common,getPlayer);
        [CRPC(org,responseInitOrg), [_finalOrg], _player] call CFUNC(targetEvent);

        _finalOrg
    }],
    ["fetch", {
        params [["_uid", "", [""]]];

        private _index = "";
        private _organization = createHashMap;
        private _orgID = "default";

        if (_uid isNotEqualTo "default") then {
            _index = GVAR(IndexRegistry) get _uid;
            _orgID = _index get "orgID";
        };

        ["org:get", [_orgID]] call EFUNC(extension,extCall) params ["_result", "_isSuccess"];
        ["INFO", format ["Data: %1", _result], nil, nil] call EFUNC(common,log);

        if (count _result > 0) then { _organization = _self call ["toHashMap", [_result]]; };

        _organization
    }],
    ["fetchAssets", {
        params [["_uid", "", [""]]];

        private _assets = createHashMap;
        private _index = GVAR(IndexRegistry) get _uid;
        private _orgID = _index get "orgID";

        ["org:assets:get", [_orgID]] call EFUNC(extension,extCall) params ["_result", "_isSuccess"];
        ["INFO", format ["Assets: %1", _result], nil, nil] call EFUNC(common,log);

        if (count _result > 0) then { _assets = _self call ["toHashMap", [_result]]; };

        _assets
    }],
    ["fetchMembers", {
        params [["_uid", "", [""]]];

        private _members = createHashMap;
        private _index = GVAR(IndexRegistry) get _uid;
        private _orgID = _index get "orgID";

        ["org:members:get", [_orgID]] call EFUNC(extension,extCall) params ["_result", "_isSuccess"];
        ["INFO", format ["Members: %1", _result], nil, nil] call EFUNC(common,log);

        private _raw_members = _self call ["toHashMap", [_result]];

        {
            private _uid = _x get "uid";
            _members set [_uid, _x];
        } forEach _raw_members;

        _members
    }],
    ["get", {
        params [["_uid", "", [""]], ["_sync", false, [false]]];

        private _finalOrg = createHashMap;
        private _index = GVAR(IndexRegistry) get _uid;
        private _orgID = _index get "orgID";

        if (_sync) then {
            _finalOrg = _self call ["fetch", [_uid]];
            GVAR(OrgRegistry) set [_orgID, _finalOrg];
        } else {
            _finalOrg = GVAR(OrgRegistry) getOrDefault [_orgID, createHashMap];
        };

        _finalOrg
    }],
    ["set", {
        params [["_uid", "", [""]], ["_field", "", [""]], ["_value", nil], ["_sync", false, [false]]];

        private _index = GVAR(IndexRegistry) get _uid;
        private _orgID = _index get "orgID";
        private _organization = GVAR(OrgRegistry) get _orgID;
        private _finalOrg = +_organization;
        private _hashMap = createHashMap;

        _finalOrg set [_field, _value];
        _hashMap set [_field, _value];

        GVAR(OrgRegistry) set [_orgID, _finalOrg];

        if (_sync) then {
            private _json = _self call ["toJSON", [_hashMap]];
            ["org:update", [_orgID, _json]] call EFUNC(extension,extCall);
        };

        private _player = [_uid] call EFUNC(common,getPlayer);
        [CRPC(org,responseSyncOrg), [_hashMap], _player] call CFUNC(targetEvent);

        _hashMap
    }],
    ["mset", {
        params [["_uid", "", [""]], ["_fieldValuePairs", createHashMap, [createHashMap]], ["_sync", false, [false]]];

        private _index = GVAR(IndexRegistry) get _uid;
        private _orgID = _index get "orgID";
        private _organization = GVAR(OrgRegistry) get _orgID;
        private _finalOrg = +_organization;
        private _hashMap = createHashMap;

        { _finalOrg set [_x, _y]; } forEach _fieldValuePairs;
        { _hashMap set [_x, _y]; } forEach _fieldValuePairs;

        GVAR(OrgRegistry) set [_orgID, _finalOrg];

        if (_sync) then {
            private _json = _self call ["toJSON", [_hashMap]];
            ["org:update", [_orgID, _json]] call EFUNC(extension,extCall);
        };

        private _player = [_uid] call EFUNC(common,getPlayer);
        [CRPC(org,responseSyncOrg), [_hashMap], _player] call CFUNC(targetEvent);

        _hashMap
    }],
    ["save", {
        params [["_uid", "", [""]], ["_sync", false, [false]]];

        private _index = GVAR(IndexRegistry) get _uid;
        private _orgID = _index get "orgID";
        private _organization = GVAR(OrgRegistry) get _orgID;
        private _finalOrg = +_organization;
        private _json = _self call ["toJSON", [_finalOrg]];

        ["org:update", [_orgID, _json]] call EFUNC(extension,extCall);

        if (_sync) then {
            private _player = [_uid] call EFUNC(common,getPlayer);
            [CRPC(org,responseSyncOrg), [_finalOrg], _player] call CFUNC(targetEvent);
        };

        _finalOrg
    }],
    ["remove", {
        params [["_uid", "", [""]]];

        private _index = GVAR(IndexRegistry) get _uid;
        private _orgID = _index get "orgID";
        GVAR(OrgRegistry) deleteAt _orgID;
    }],
    ["toHashMap", {
        params [["_data", "", [""]]];

        private _hashMap = fromJSON _data;
        _hashMap
    }],
    ["toJSON", {
        params [["_data", createHashMap, [createHashMap]]];

        private _json = toJSON _data;
        _json
    }]
]];

SETMVAR(FORGE_OrgStore,GVAR(OrgStore));
GVAR(OrgStore)
