#include "..\script_component.hpp"

/*
 * Function: forge_client_org_fnc_initOrgStore
 * Author: IDSolutions
 * 
 * Description:
 * Initializes a client-side organization store interface for managing player organization data
 * Provides CRUD operations for organizations, including database persistence through ArmaDragonflyClient
 *
 * Creates a hashMap object with methods for:
 * - Creating, loading, and saving organizations
 * - Managing organization funds and reputation
 * - Adding, removing, and querying organization members and assets
 *
 * Returns:
 * Organization store interface <HASHMAP>
 *
 * Example:
 * private _orgStore = call forge_client_org_fnc_initOrgStore;
 * _orgStore call ["createOrg", [getPlayerUID player, "My Organization"]];
 */

private _orgStoreInterface = createHashMapObject [[
    ["#type", "IOrganizationStore"],
    ["#create", {
        /**
         * Initializes the organization store interface
         * 
         * Sets up the initial state of the organization store:
         * - Clears any existing organization data
         * - Sets the current user's UID as the playerUID
         * - Marks the store as not loaded
         * - Triggers database loading of organization data
         *
         * @return {Boolean} True if initialization was successful
         */
        _self set ["currentOrganization", nil];
        _self set ["playerUID", getPlayerUID player];
        _self set ["isLoaded", false];

        _self call ["loadFromDatabase", []];

        true
    }],
    ["loadFromDatabase", {
        /**
         * Loads organization data from the database
         * 
         * Retrieves organization data associated with the current player's UID
         * from the database using the ArmaDragonflyClient database system.
         * Sets isLoaded to false until the data is retrieved and processed by
         * the handleOrgLoad callback function.
         *
         * @return {Void} No return value
         */
        private _playerUID = _self get "playerUID";
        private _orgID = format ["%1_org", _playerUID];

        ["hgetallid", _orgID, "", -1, [], QFUNC(handleOrgLoad), false, netId player] remoteExecCall ["dragonfly_db_fnc_addTask", 2, false];

        _self set ["isLoaded", false];
    }],
    ["saveToDatabase", {
        /**
         * Saves the current organization data to the database
         * 
         * Processes the organization data structure for database storage:
         * - Serializes string values for name and owner
         * - Converts the members hashMap to a flattened array format
         * - Converts the assets hashMap to a flattened array format
         * - Sends the processed data to the database using ArmaDragonflyClient
         *
         * @return {Boolean} True if save was successful, false if no organization data exists
         */
        private _orgData = _self get "currentOrganization";

        if (isNil "_orgData") exitWith { 
            ["No organization data to save", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _processedData = createHashMapFromArray [];
        {
            private _key = _x;
            private _value = _orgData get _key;

            if (_key in ["name", "owner"] && _value isEqualType "") then {
                _value = [_value] call EFUNC(misc,serializeString);
            };

            // Convert members hashMap back to array format for storage
            if (_key == "members" && _value isEqualType createHashMap) then {
                private _flattenedMembers = [];
                {
                    private _uid = _x;
                    private _memberMap = _value get _uid;

                    if (!isNil "_memberMap") then {
                        private _name = _memberMap get "name";
                        // Replace spaces with underscores for storage
                        if (_name isEqualType "") then {
                            _name = [_name] call EFUNC(misc,serializeString);
                        };

                        private _role = _memberMap get "role";
                        private _joinDate = _memberMap get "joinDate";
                        private _memberArray = [_uid, _name, _role, _joinDate];

                        // Add any additional properties
                        {
                            if !(_x in ["uid", "name", "role", "joinDate"]) then {
                                _memberArray pushBack _x;
                                _memberArray pushBack (_memberMap get _x);
                            };
                        } forEach (keys _memberMap);

                        _flattenedMembers pushBack _memberArray;
                    };
                } forEach (keys _value);

                _value = _flattenedMembers;
            };

            // Convert assets hashMap back to flat array for storage
            if (_key == "assets" && _value isEqualType createHashMap) then {
                private _flattenedAssets = [];
                {
                    private _type = _x;
                    private _typeAssets = _value get _type;

                    {
                        private _assetMap = _x;
                        private _id = _assetMap get "id";
                        private _className = _assetMap get "className";
                        private _flatAsset = [_type, _className, "id", _id];

                        // Add all other properties as key-value pairs
                        {
                            if (_x != "className" && _x != "id") then {
                                _flatAsset pushBack _x;
                                _flatAsset pushBack (_assetMap get _x);
                            };
                        } forEach (keys _assetMap);

                        _flattenedAssets pushBack _flatAsset;
                    } forEach _typeAssets;
                } forEach (keys _value);

                _value = _flattenedAssets;
            };

            _processedData set [_key, _value];
        } forEach (keys _orgData);

        private _data = [
            _processedData get "id",
            "id", [_processedData get "id"],
            "name", [_processedData get "name"],
            "owner", [_processedData get "owner"],
            "funds", [_processedData get "funds"],
            "reputation", [_processedData get "reputation"],
            "assets", [_processedData get "assets"],
            "members", [_processedData get "members"],
            "logs", [_processedData get "logs"],
            "created", [_processedData get "created"],
            "lastModified", [_processedData get "lastModified"]
        ];

        ["hsetidbulk", "", "", -1, _data, "", false, netId player] remoteExecCall ["dragonfly_db_fnc_addTask", 2, false];
        true
    }],
    ["generateOrgID", {
        /**
         * Generates a unique organization ID based on the owner's UID
         * 
         * Creates a standardized organization ID format by appending "_org" 
         * to the player's UID, ensuring consistent ID generation for database storage.
         *
         * @param {String} _uid The player UID to use as the base for the organization ID
         * @return {String} The generated organization ID, or empty string if UID is invalid
         */
        params [["_uid", "", [""]]];

        if (_uid == "") exitWith { 
            ["Owner UID cannot be empty", "error", 5, "right"] call forge_client_misc_fnc_notify;
            "" 
        };

        private _orgID = format ["%1_org", _uid];
        _orgID
    }],
    ["createOrg", {
        /**
         * Creates a new organization with the specified parameters
         * 
         * Initializes a new organization with the given name and owner,
         * setting up the initial structure with default values for funds,
         * reputation, assets, members, and logs. Adds the current player
         * as the owner in the members list and saves to the database.
         *
         * @param {String} _uid The player UID who will be the organization owner
         * @param {String} _name The name of the organization
         * @param {Number} _initialFunds Starting funds for the organization (default: 0)
         * @param {Number} _initialReputation Starting reputation for the organization (default: 0)
         * @return {HashMap} The newly created organization data, or nil if creation failed
         */
        params [["_uid", "", [""]], ["_name", "", [""]], ["_initialFunds", 0, [0]], ["_initialReputation", 0, [0]]];

        if (_uid == "" || _name == "") exitWith { 
            ["Owner UID and name cannot be empty", "error", 5, "right"] call forge_client_misc_fnc_notify;
            nil 
        };
        
        if (!isNil {_self get "currentOrganization"}) exitWith { 
            ["You are already part of an organization", "warning", 5, "right"] call forge_client_misc_fnc_notify;
            nil 
        };

        private _dateTime = call EFUNC(misc,getSystemTime);
        private _orgID = _self call ["generateOrgID", [_uid]];
        private _orgData = createHashMapFromArray [
            ["id", _orgID],
            ["name", _name],
            ["owner", _uid],
            ["funds", _initialFunds],
            ["reputation", _initialReputation],
            ["assets", createHashMap],
            ["members", createHashMap],
            ["logs", []],
            ["created", _dateTime],
            ["lastModified", _dateTime]
        ];

        // Create owner member entry
        private _memberMap = createHashMap;
        _memberMap set ["uid", _uid];
        _memberMap set ["name", name player];
        _memberMap set ["role", "owner"];
        _memberMap set ["joinDate", _dateTime];

        // Add to members hashMap
        private _members = _orgData get "members";
        _members set [_uid, _memberMap];
        _orgData set ["members", _members];

        _self set ["currentOrganization", _orgData];
        _self call ["saveToDatabase", []];

        SETPVAR(player,FORGE_Organization,_orgID);

        _orgData
    }],
    ["getOrg", {
        /**
         * Retrieves the current organization data
         * 
         * Gets the organization data for the current player. If the data
         * hasn't been loaded yet, waits until the loading process completes
         * before returning the data.
         *
         * @return {HashMap} The current organization data, or nil if not in an organization
         */
        if (!(_self get "isLoaded")) then {
            waitUntil { _self get "isLoaded" };
        };

        _self get "currentOrganization"
    }],
    ["syncWithDatabase", {
        /**
         * Synchronizes the current organization data with the database
         * 
         * Updates the lastModified timestamp and saves the current
         * organization data to the database. Used to ensure database
         * consistency after making changes to the organization.
         *
         * @return {Boolean} True if sync was successful, false if no organization data exists
         */
        private _orgData = _self get "currentOrganization";

        if (isNil "_orgData") exitWith { 
            ["No organization data to sync", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        _orgData set ["lastModified", call EFUNC(misc,getSystemTime)];
        _self set ["currentOrganization", _orgData];
        _self call ["saveToDatabase", []];

        true
    }],
    ["updateFunds", {
        /**
         * Updates the organization's funds balance
         * 
         * Adds or subtracts the specified amount from the organization's funds.
         * Records the transaction in the organization logs with timestamp,
         * amount changed, and new balance.
         *
         * @param {Number} _amount The amount to add (positive) or subtract (negative)
         * @return {Boolean} True if update was successful, false if no organization exists
         */
        params [["_amount", 0, [0]]];

        private _orgData = _self call ["getOrg", []];

        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _funds = _orgData get "funds";
        private _dateTime = call EFUNC(misc,getSystemTime);

        private _newFunds = _funds + _amount;
        _orgData set ["funds", _newFunds];
        _orgData set ["lastModified", _dateTime];

        // Add to logs
        private _logs = _orgData get "logs";
        _logs pushBack [_dateTime, "FUNDS_UPDATED", _amount, _newFunds];
        _orgData set ["logs", _logs];

        _self set ["currentOrganization", _orgData];
        _self call ["saveToDatabase", []];

        true
    }],
    ["getFunds", {
        /**
         * Retrieves the current funds balance of the organization
         * 
         * Gets the current financial balance of the organization.
         * Used for displaying funds or checking if sufficient funds
         * are available for transactions.
         *
         * @return {Number} The current funds amount, or nil if no organization exists
         */
        private _orgData = _self call ["getOrg", []];

        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            nil 
        };

        _orgData getOrDefault ["funds", 0]
    }],
    ["updateReputation", {
        /**
         * Updates the organization's reputation value
         * 
         * Adds or subtracts the specified amount from the organization's reputation.
         * Records the change in the organization logs with timestamp,
         * amount changed, and new reputation value.
         *
         * @param {Number} _amount The amount to add (positive) or subtract (negative)
         * @return {Boolean} True if update was successful, false if no organization exists
         */
        params [["_amount", 0, [0]]];

        private _orgData = _self call ["getOrg", []];

        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _reputation = _orgData get "reputation";
        private _newReputation = _reputation + _amount;
        _orgData set ["reputation", _newReputation];
        _orgData set ["lastModified", call EFUNC(misc,getSystemTime)];

        // Add to logs
        private _dateTime = call EFUNC(misc,getSystemTime);
        private _logs = _orgData get "logs";
        _logs pushBack [_dateTime, "REPUTATION_UPDATED", _amount, _newReputation];
        _orgData set ["logs", _logs];

        _self set ["currentOrganization", _orgData];
        _self call ["saveToDatabase", []];

        true
    }],
    ["getReputation", {
        /**
         * Retrieves the current reputation value of the organization
         * 
         * Gets the current reputation score of the organization.
         * Used for displaying reputation or checking if sufficient reputation
         * is available for certain actions or unlocks.
         *
         * @return {Number} The current reputation value, or nil if no organization exists
         */
        private _orgData = _self call ["getOrg", []];

        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            nil 
        };

        _orgData getOrDefault ["reputation", 0]
    }],
    ["addAsset", {
        /**
         * Adds a new asset to the organization's inventory
         * 
         * Creates and stores a new asset entry in the organization's assets collection.
         * Assets are organized by type (vehicles, buildings, etc.) and include
         * a unique ID, class name, and any additional custom properties.
         * Records the addition in the organization logs.
         *
         * @param {String} _assetType The category/type of the asset (e.g., "vehicle", "building")
         * @param {String} _className The class name of the asset in the game
         * @param {HashMap} _properties Additional properties to store with the asset
         * @return {String} The generated unique ID for the asset, or false if failed
         */
        params [["_assetType", "", [""]], ["_className", "", [""]], ["_properties", createHashMap, [createHashMap]]];

        if (_assetType == "" || _className == "") exitWith { 
            ["Asset type and className cannot be empty", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _orgData = _self call ["getOrg", []];
        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _assets = _orgData get "assets";
        if !(_assets isEqualType createHashMap) then {
            _assets = createHashMap;
        };

        // Get or create the asset type array
        private _typeAssets = _assets getOrDefault [_assetType, []];

        // Generate a unique ID for this asset
        private _assetId = format ["%1_%2", _className, call EFUNC(misc,getSystemTime)];

        // Create the asset hashMap
        private _assetMap = createHashMap;
        _assetMap set ["id", _assetId]; 
        _assetMap set ["className", _className];

        // Add all provided properties
        {
            if (_x != "className" && _x != "id") then {
                _assetMap set [_x, _properties get _x];
            };
        } forEach (keys _properties);

        // Add as a new asset
        _typeAssets pushBack _assetMap;

        _assets set [_assetType, _typeAssets];
        _orgData set ["assets", _assets];
        _orgData set ["lastModified", call EFUNC(misc,getSystemTime)];

        // Add to logs
        private _dateTime = call EFUNC(misc,getSystemTime);
        private _logs = _orgData get "logs";
        _logs pushBack [_dateTime, "ASSET_ADDED", _assetType, _className, _assetId];
        _orgData set ["logs", _logs];

        _self set ["currentOrganization", _orgData];
        _self call ["saveToDatabase", []];

        _assetId // Return the generated ID
    }],
    ["getAssets", {
        /**
         * Retrieves assets from the organization's inventory
         * 
         * Flexible method to get assets from the organization with multiple retrieval options:
         * - Get all assets across all types
         * - Get all assets of a specific type
         * - Get a specific asset by ID or className
         *
         * @param {String} _assetType Optional type/category to filter assets (empty for all types)
         * @param {String} _idOrClassName Optional ID or className to find a specific asset
         * @param {Boolean} _findById If true, search by ID; if false, search by className
         * @return {Array|HashMap|Nil} Asset data based on search parameters, or nil if not found
         */
        params [["_assetType", "", [""]], ["_idOrClassName", "", [""]], ["_findById", false, [false]]];

        private _orgData = _self call ["getOrg", []];
        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            nil 
        };

        private _assets = _orgData get "assets";
        if !(_assets isEqualType createHashMap) then {
            _assets = createHashMap;
        };

        // Get specific asset by ID or className
        if (_assetType != "" && _idOrClassName != "") then {
            private _typeAssets = _assets getOrDefault [_assetType, []];
            private _index = -1;

            if (_findById) then {
                _index = _typeAssets findIf {(_x get "id") == _idOrClassName};
            } else {
                // Get first matching className (for backward compatibility)
                _index = _typeAssets findIf {(_x get "className") == _idOrClassName};
            };

            if (_index != -1) then {
                _typeAssets select _index
            } else {
                nil
            }
        } else {
            if (_assetType != "") then {
                _assets getOrDefault [_assetType, []]
            } else {
                private _allAssets = [];
                {
                    private _type = _x;
                    private _typeAssets = _assets get _type;
                    {
                        private _assetMap = _x;
                        private _id = _assetMap get "id";
                        private _className = _assetMap get "className";
                        private _flatAsset = [_type, _className, "id", _id];

                        // Add all other properties as key-value pairs
                        {
                            if (_x != "className" && _x != "id") then {
                                _flatAsset pushBack _x;
                                _flatAsset pushBack (_assetMap get _x);
                            };
                        } forEach (keys _assetMap);

                        _allAssets pushBack _flatAsset;
                    } forEach _typeAssets;
                } forEach (keys _assets);

                _allAssets
            }
        }
    }],
    ["removeAsset", {
        /**
         * Removes an asset from the organization's inventory
         * 
         * Deletes a specific asset from the organization's assets collection
         * based on its type and unique ID. Records the removal in the 
         * organization logs with details about the removed asset.
         *
         * @param {String} _assetType The category/type of the asset to remove
         * @param {String} _assetId The unique ID of the asset to remove
         * @return {Boolean} True if asset was successfully removed, false if not found or error
         */
        params [["_assetType", "", [""]], ["_assetId", "", [""]]];

        if (_assetType == "" || _assetId == "") exitWith { 
            ["Asset type and asset ID cannot be empty", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _orgData = _self call ["getOrg", []];
        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _assets = _orgData get "assets";
        if !(_assets isEqualType createHashMap) then {
            _assets = createHashMap;
        };

        private _typeAssets = _assets getOrDefault [_assetType, []];
        private _index = _typeAssets findIf {(_x get "id") == _assetId};

        if (_index != -1) then {
            private _asset = _typeAssets select _index;
            private _className = _asset get "className";

            _typeAssets deleteAt _index;
            _assets set [_assetType, _typeAssets];
            _orgData set ["assets", _assets];

            // Add to logs
            private _dateTime = call EFUNC(misc,getSystemTime);
            private _logs = _orgData get "logs";
            _logs pushBack [_dateTime, "ASSET_REMOVED", _assetType, _className, _assetId];
            _orgData set ["logs", _logs];

            _orgData set ["lastModified", call EFUNC(misc,getSystemTime)];
            _self set ["currentOrganization", _orgData];
            _self call ["saveToDatabase", []];

            true
        } else {
            false
        };
    }],
    ["addMember", {
        /**
         * Adds a new member to the organization
         * 
         * Creates and stores a new member entry in the organization's members collection.
         * Only the organization owner can add new members. Each member has a UID, name,
         * role, and join date. Records the addition in the organization logs.
         *
         * @param {String} _uid The unique player ID of the member to add
         * @param {String} _name The display name of the member
         * @param {String} _role The role/rank of the member in the organization (default: "member")
         * @return {Boolean} True if member was successfully added, false if error or not authorized
         */
        params [["_uid", "", [""]], ["_name", "", [""]], ["_role", "member", [""]]];

        if (_uid == "" || _name == "") exitWith { 
            ["Member UID and name cannot be empty", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _orgData = _self call ["getOrg", []];
        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _playerUID = _self get "playerUID";
        if ((_orgData get "owner") != _playerUID) exitWith { 
            ["Only the owner can add members", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _members = _orgData get "members";
        if !(_members isEqualType createHashMap) then {
            _members = createHashMap;
        };

        // Check if member already exists
        if (!isNil {_members get _uid}) exitWith { 
            private _errorMsg = format ["Member already in this organization: %1", _uid];
            [_errorMsg, "warning", 5, "right"] call forge_client_misc_fnc_notify;
            true 
        };

        // Create member hashMap
        private _memberMap = createHashMap;
        private _joinDate = call EFUNC(misc,getSystemTime);

        // Add member data to hashMap
        _memberMap set ["uid", _uid];
        _memberMap set ["name", _name];
        _memberMap set ["role", _role];
        _memberMap set ["joinDate", _joinDate];

        // Add to members hashMap
        _members set [_uid, _memberMap];
        _orgData set ["members", _members];
        _orgData set ["lastModified", call EFUNC(misc,getSystemTime)];

        // Add to logs
        private _dateTime = call EFUNC(misc,getSystemTime);
        private _logs = _orgData get "logs";
        _logs pushBack [_dateTime, "MEMBER_ADDED", _uid, _name, _role];
        _orgData set ["logs", _logs];

        _self set ["currentOrganization", _orgData];
        _self call ["saveToDatabase", []];

        true
    }],
    ["removeMember", {
        /**
         * Removes a member from the organization
         * 
         * Deletes a member from the organization's members collection based on their UID.
         * Only the organization owner can remove members, and the owner cannot remove themselves.
         * Records the removal in the organization logs.
         *
         * @param {String} _uid The unique player ID of the member to remove
         * @return {Boolean} True if member was successfully removed, false if not found or not authorized
         */
        params [["_uid", "", [""]]];

        if (_uid == "") exitWith { 
            ["Member UID cannot be empty", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _orgData = _self call ["getOrg", []];
        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _playerUID = _self get "playerUID";
        if ((_orgData get "owner") != _playerUID) exitWith { 
            ["Only the owner can remove members", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _members = _orgData get "members";
        if !(_members isEqualType createHashMap) then {
            _members = createHashMap;
        };

        // Get member and check if they exist
        private _memberMap = _members get _uid;
        if (isNil "_memberMap") exitWith { 
            private _errorMsg = format ["Member not in organization: %1", _uid];
            [_errorMsg, "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        // Check if trying to remove the owner
        if ((_memberMap get "role") == "owner") exitWith { 
            ["Cannot remove the organization owner", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        // Get name for logging
        private _name = _memberMap get "name";

        // Remove from hashMap
        _members deleteAt _uid;
        _orgData set ["members", _members];
        _orgData set ["lastModified", call EFUNC(misc,getSystemTime)];

        // Add to logs
        private _dateTime = call EFUNC(misc,getSystemTime);
        private _logs = _orgData get "logs";
        _logs pushBack [_dateTime, "MEMBER_REMOVED", _uid, _name];
        _orgData set ["logs", _logs];

        _self set ["currentOrganization", _orgData];
        _self call ["saveToDatabase", []];

        [format ["Member %1 removed from organization", _name], "info", 5, "right"] call forge_client_misc_fnc_notify;

        true
    }],
    ["getMembers", {
        /**
         * Retrieves members from the organization
         * 
         * Gets either a specific member by UID or all members of the organization.
         * Returns member data including UID, name, role, and join date.
         *
         * @param {String} _uid Optional UID to get a specific member (empty for all members)
         * @return {HashMap|Array|Nil} Member data for specific member, array of all members, or nil if error
         */
        params [["_uid", "", [""]]];

        private _orgData = _self call ["getOrg", []];
        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            nil 
        };

        private _members = _orgData get "members";
        if !(_members isEqualType createHashMap) then {
            _members = createHashMap;
        };

        // Get specific member by UID
        if (_uid != "") then {
            _members get _uid
        } else {
            // Get all members
            private _allMembers = [];
            {
                _allMembers pushBack (_members get _x);
            } forEach (keys _members);

            _allMembers
        }
    }],
    ["deleteOrg", {
        /**
         * Deletes the entire organization
         * 
         * Permanently removes the organization from the database.
         * Only the organization owner can delete the organization.
         * Clears the current organization data from the store after deletion.
         *
         * @return {Boolean} True if organization was successfully deleted, false if not authorized
         */
        private _orgData = _self call ["getOrg", []];

        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _playerUID = _self get "playerUID";
        if ((_orgData get "owner") != _playerUID) exitWith { 
            ["Only the owner can delete the organization", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _orgID = _orgData get "id";
        ["del", _orgID, "", -1, [], "", false, netId player] remoteExecCall ["dragonfly_db_fnc_addTask", 2, false];

        _self set ["currentOrganization", nil];
        _self set ["isLoaded", true];

        true
    }],
    ["leaveOrg", {
        /**
         * Removes the current player from the organization
         * 
         * Allows a member to leave the organization they're currently in.
         * The organization owner cannot use this method (must use deleteOrg instead).
         * Records the departure in the organization logs before removing player access.
         *
         * @return {Boolean} True if player successfully left the organization, false if error or owner
         */
        private _orgData = _self call ["getOrg", []];
        if (isNil "_orgData") exitWith { 
            ["No organization found", "error", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _playerUID = _self get "playerUID";
        if ((_orgData get "owner") == _playerUID) exitWith { 
            ["Organization owner cannot leave, must delete instead", "warning", 5, "right"] call forge_client_misc_fnc_notify;
            false 
        };

        private _members = _orgData get "members";
        if !(_members isEqualType createHashMap) then {
            _members = createHashMap;
        };

        // Get member data
        private _memberMap = _members get _playerUID;
        if (!isNil "_memberMap") then {
            private _dateTime = call EFUNC(misc,getSystemTime);
            private _memberName = _memberMap get "name";

            // Add to logs
            private _logs = _orgData get "logs";
            _logs pushBack [_dateTime, "MEMBER_LEFT", _playerUID, _memberName];
            _orgData set ["logs", _logs];

            _self call ["saveToDatabase", []];
        };

        _self set ["currentOrganization", nil];
        _self set ["isLoaded", true];

        ["You have left the organization", "info", 5, "right"] call forge_client_misc_fnc_notify;

        true
    }]
]];

SETMVAR(FORGE_ORG_STORE_REG,_orgStoreInterface);
GETMVAR(FORGE_ORG_STORE_REG,_orgStoreInterface)