/*
    Examine NUI Windows
    Created By: Daz
*/

#include "inc_nui"
#include "inc_util"

const string EXAMINE_NUI_WINDOW_ID          = "EXAMINEWINDOW";
const string EXAMINE_WINDOW_GEOMETRY_JSON   = "EXAMINE_WINDOW_GEOMETRY_JSON";
const string EXAMINE_GENERIC_WINDOW_JSON    = "EXAMINE_GENERIC_WINDOW_JSON";
const string EXAMINE_ITEM_WINDOW_JSON       = "EXAMINE_ITEM_WINDOW_JSON";

const string EXAMINE_CURRENT_WINDOW_TYPE    = "EXAMINE_CURRENT_WINDOW_TYPE";
const string EXAMINE_CURRENT_OBJECT         = "EXAMINE_CURRENT_OBJECT";

const float EXAMINE_GENERIC_WINDOW_WIDTH    = 500.0f;
const float EXAMINE_GENERIC_WINDOW_HEIGHT   = 255.0f;

const float EXAMINE_ITEM_WINDOW_WIDTH       = 500.0f;
const float EXAMINE_ITEM_WINDOW_HEIGHT      = 400.0f;

void Examine_DisablePanels(object oPlayer);
json Examine_GetWindowJson(int nPanel);
json Examine_GetGenericWindowJson();
json Examine_GetItemWindowJson();
float Examine_GetWindowWidth(int nPanel);
float Examine_GetWindowHeight(int nPanel);

void Examine_HandleGUIEvents(object oPlayer, object oTarget, int nPanel);
void Examine_HandleNUIEvents(object oPlayer, int nToken, string sType, string sElement, int nArrayIndex);

void Examine_SetData(object oPlayer, int nToken, object oTarget, int nPanel);
void Examine_SetGenericData(object oPlayer, int nToken, object oTarget, int nPanel);
string Examine_GetItemPropertyString(itemproperty ip);
void Examine_SetItemData(object oPlayer, int nToken, object oItem);


void Examine_DisablePanels(object oPlayer)
{
    SetGuiPanelDisabled(oPlayer, GUI_PANEL_EXAMINE_CREATURE, TRUE);
    SetGuiPanelDisabled(oPlayer, GUI_PANEL_EXAMINE_ITEM, TRUE);
    SetGuiPanelDisabled(oPlayer, GUI_PANEL_EXAMINE_PLACEABLE, TRUE);
    SetGuiPanelDisabled(oPlayer, GUI_PANEL_EXAMINE_DOOR, TRUE);
}

json Examine_GetWindowJson(int nPanel)
{
    json jWindow;
    switch (nPanel)
    {
        case GUI_PANEL_EXAMINE_CREATURE:
        case GUI_PANEL_EXAMINE_PLACEABLE:
        case GUI_PANEL_EXAMINE_DOOR:
            jWindow = Examine_GetGenericWindowJson();
            break;
        case GUI_PANEL_EXAMINE_ITEM:
            jWindow = Examine_GetItemWindowJson();
            break;
    }

    return jWindow;
}

json Examine_GetGenericWindowJson()
{
    json jRoot = GetLocalJson(GetModule(), EXAMINE_GENERIC_WINDOW_JSON);
    if (jRoot == JsonNull())
    {
        json jCol = JsonArray(), jRow;
        jRow = JsonArray();
        {
            json jSubCol, jSubRow;

            jSubCol = JsonArray();
                // Image
                jSubRow = JsonArray();
                {
                    json jImage = NuiImage(NuiBind("image_1"), JsonInt(NUI_ASPECT_EXACTSCALED), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP));
                         jImage = NuiWidth(jImage, 64.0f);
                         jImage = NuiHeight(jImage, 100.0f);
                    jSubRow = JsonArrayInsert(jSubRow, jImage);
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);

                // Spacer
                jSubRow = JsonArray();
                {
                    jSubRow = JsonArrayInsert(jSubRow, NuiSpacer());
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);
            jRow = JsonArrayInsert(jRow, NuiCol(jSubCol));

            jSubCol = JsonArray();
                // Description Label
                jSubRow = JsonArray();
                {
                    json jHeader = NuiHeader(JsonString("Description"));
                    jSubRow = JsonArrayInsert(jSubRow, jHeader);
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);

                // Description Text
                jSubRow = JsonArray();
                {
                    json jDescription = NuiText(NuiBind("description"));
                         jDescription = NuiHeight(jDescription, 160.0f);
                    jSubRow = JsonArrayInsert(jSubRow, jDescription);
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);

                // Spacer
                jSubRow = JsonArray();
                {
                    jSubRow = JsonArrayInsert(jSubRow, NuiSpacer());
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);
            jRow = JsonArrayInsert(jRow, NuiCol(jSubCol));
        }
        jCol = NuiInsertRow(jCol, jRow);

        jRoot = NuiCol(jCol);
        SetLocalJson(GetModule(), EXAMINE_GENERIC_WINDOW_JSON, jRoot);
    }

    return jRoot;
}

json Examine_GetItemWindowJson()
{
    json jRoot = GetLocalJson(GetModule(), EXAMINE_ITEM_WINDOW_JSON);
    if (jRoot == JsonNull())
    {
        json jCol = JsonArray(), jRow;
        jRow = JsonArray();
        {
            json jSubCol, jSubRow;

            jSubCol = JsonArray();
                // Image
                jSubRow = JsonArray();
                {
                    json jImage = NuiImage(NuiBind("image_1"), JsonInt(NUI_ASPECT_EXACTSCALED), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP));
                         json jRect = NuiRect(0.0f, 0.0f, 64.0f, 192.0f);
                         json jDrawList = JsonArray();
                              jDrawList = JsonArrayInsert(jDrawList, NuiDrawListImage(NuiBind("complex_item"), NuiBind("image_2"), jRect, JsonInt(NUI_ASPECT_EXACTSCALED), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP)));
                              jDrawList = JsonArrayInsert(jDrawList, NuiDrawListImage(NuiBind("complex_item"), NuiBind("image_3"), jRect, JsonInt(NUI_ASPECT_EXACTSCALED), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP)));
                         jImage = NuiDrawList(jImage, JsonBool(TRUE), jDrawList);
                         jImage = NuiWidth(jImage, 64.0f);
                         jImage = NuiHeight(jImage, 192.0f);
                    jSubRow = JsonArrayInsert(jSubRow, jImage);
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);

                // Button?
                jSubRow = JsonArray();
                {
                    json jButton = NuiButton(JsonString("Button?"));
                         jButton = NuiId(jButton, "btn_button");
                         jButton = NuiWidth(jButton, 64.0f);
                         jButton = NuiHeight(jButton, 35.0f);
                    jSubRow = JsonArrayInsert(jSubRow, jButton);
                }
                //jSubCol = NuiInsertRow(jSubCol, jSubRow);

                // Spacer
                jSubRow = JsonArray();
                {
                    jSubRow = JsonArrayInsert(jSubRow, NuiSpacer());
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);
            jRow = JsonArrayInsert(jRow, NuiCol(jSubCol));

            jSubCol = JsonArray();
                // Description Label
                jSubRow = JsonArray();
                {
                    json jHeader = NuiHeader(JsonString("Description"));
                    jSubRow = JsonArrayInsert(jSubRow, jHeader);
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);

                // Description Text
                jSubRow = JsonArray();
                {
                    json jDescription = NuiText(NuiBind("description"));
                         jDescription = NuiHeight(jDescription, 160.0f);
                    jSubRow = JsonArrayInsert(jSubRow, jDescription);
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);

                // Item Properties Label
                jSubRow = JsonArray();
                {
                    json jHeader = NuiHeader(JsonString("Item Properties"));
                    jSubRow = JsonArrayInsert(jSubRow, jHeader);
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);

                // Item Properties List
                jSubRow = JsonArray();
                {
                    json jListTemplate = JsonArray();
                    {
                        json jLabel = NuiLabel(NuiBind("property"), JsonInt(NUI_HALIGN_LEFT), JsonInt(NUI_VALIGN_MIDDLE));
                             jLabel = NuiStyleForegroundColor(jLabel, NuiBind("color"));
                        jListTemplate = JsonArrayInsert(jListTemplate, NuiListTemplateCell(jLabel, 0.0f, TRUE));
                    }
                    json jList = NuiList(jListTemplate, NuiBind("property"), 16.0f);
                         jList = NuiHeight(jList, 105.0f);
                    jSubRow = JsonArrayInsert(jSubRow, jList);
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);

                // Spacer
                jSubRow = JsonArray();
                {
                    jSubRow = JsonArrayInsert(jSubRow, NuiSpacer());
                }
                jSubCol = NuiInsertRow(jSubCol, jSubRow);
            jRow = JsonArrayInsert(jRow, NuiCol(jSubCol));
        }
        jCol = NuiInsertRow(jCol, jRow);

        jRoot = NuiCol(jCol);
        SetLocalJson(GetModule(), EXAMINE_ITEM_WINDOW_JSON, jRoot);
    }

    return jRoot;
}

float Examine_GetWindowWidth(int nPanel)
{
    float fWidth;
    switch (nPanel)
    {
        case GUI_PANEL_EXAMINE_CREATURE:
        case GUI_PANEL_EXAMINE_PLACEABLE:
        case GUI_PANEL_EXAMINE_DOOR:
            fWidth = EXAMINE_GENERIC_WINDOW_WIDTH;
            break;
        case GUI_PANEL_EXAMINE_ITEM:
            fWidth = EXAMINE_ITEM_WINDOW_WIDTH;
            break;
    }

    return fWidth;
}

float Examine_GetWindowHeight(int nPanel)
{
    float fHeight;
    switch (nPanel)
    {
        case GUI_PANEL_EXAMINE_CREATURE:
        case GUI_PANEL_EXAMINE_PLACEABLE:
        case GUI_PANEL_EXAMINE_DOOR:
            fHeight = EXAMINE_GENERIC_WINDOW_HEIGHT;
            break;
        case GUI_PANEL_EXAMINE_ITEM:
            fHeight = EXAMINE_ITEM_WINDOW_HEIGHT;
            break;
    }

    return fHeight;
}

void Examine_HandleGUIEvents(object oPlayer, object oTarget, int nPanel)
{
    json jGeometry = GetLocalJson(oPlayer, EXAMINE_WINDOW_GEOMETRY_JSON);

    int nToken = NuiFindWindow(oPlayer, EXAMINE_NUI_WINDOW_ID);
    if (nToken)
    {
        if (GetLocalObject(oPlayer, EXAMINE_CURRENT_OBJECT) == oTarget)
            return;

        int bIsItemExamine = nPanel == GUI_PANEL_EXAMINE_ITEM;
        int nCurrentWindowType = GetLocalInt(oPlayer, EXAMINE_CURRENT_WINDOW_TYPE);

        if (bIsItemExamine && nCurrentWindowType != GUI_PANEL_EXAMINE_ITEM)
        {
            NuiSetGroupLayout(oPlayer, nToken, NUI_WINDOW_ROOT_GROUP, Examine_GetWindowJson(nPanel));
            NuiSetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, NuiSetRectHeight(jGeometry, Examine_GetWindowHeight(nPanel)));
        }
        else if (!bIsItemExamine && nCurrentWindowType == GUI_PANEL_EXAMINE_ITEM)
        {
            NuiSetGroupLayout(oPlayer, nToken, NUI_WINDOW_ROOT_GROUP, Examine_GetWindowJson(nPanel));
            NuiSetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, NuiSetRectHeight(jGeometry, Examine_GetWindowHeight(nPanel)));
        }

        Examine_SetData(oPlayer, nToken, oTarget, nPanel);

        SetLocalInt(oPlayer, EXAMINE_CURRENT_WINDOW_TYPE, nPanel);
        SetLocalObject(oPlayer, EXAMINE_CURRENT_OBJECT, oTarget);

        return;
    }

    json jRoot = Examine_GetWindowJson(nPanel);
    json jWindow = NuiWindow(jRoot, NuiBind(NUI_WINDOW_TITLE_BIND), NuiBind(NUI_WINDOW_GEOMETRY_BIND), JsonBool(FALSE), JsonNull(), JsonBool(TRUE), JsonBool(FALSE), JsonBool(TRUE));

    float fWidth = Examine_GetWindowWidth(nPanel);
    float fHeight = Examine_GetWindowHeight(nPanel);

    if (jGeometry == JsonNull())
        jGeometry = NuiGetCenteredGeometryRect(oPlayer, fWidth, fHeight);
    else
    {
        jGeometry = NuiSetRectWidth(jGeometry, fWidth);
        jGeometry = NuiSetRectHeight(jGeometry, fHeight);
    }

    nToken = NuiCreate(oPlayer, jWindow, EXAMINE_NUI_WINDOW_ID);

    NuiSetBindWatch(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, TRUE);
    NuiSetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, jGeometry);

    Examine_SetData(oPlayer, nToken, oTarget, nPanel);

    SetLocalInt(oPlayer, EXAMINE_CURRENT_WINDOW_TYPE, nPanel);
    SetLocalObject(oPlayer, EXAMINE_CURRENT_OBJECT, oTarget);
}

void Examine_HandleNUIEvents(object oPlayer, int nToken, string sType, string sElement, int nArrayIndex)
{
    if (sType == NUI_EVENT_CLOSE)
    {
        DeleteLocalInt(oPlayer, EXAMINE_CURRENT_WINDOW_TYPE);
        DeleteLocalObject(oPlayer, EXAMINE_CURRENT_OBJECT);
    }
    else if (sType == NUI_EVENT_WATCH)
    {
        if (sElement == NUI_WINDOW_GEOMETRY_BIND)
        {
            SetLocalJson(oPlayer, EXAMINE_WINDOW_GEOMETRY_JSON, NuiGetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND));
        }
    }
}

int Examine_HandleIdentifyItem(object oPlayer, object oItem)
{
    int bIdentified = GetIdentified(oItem);

    if (!bIdentified)
    {
        int nIdentifySkillRank = GetSkillRank(SKILL_LORE, oPlayer);

        if (nIdentifySkillRank < 0)
            return FALSE;
        if (nIdentifySkillRank > 55)
        {
            SetIdentified(oItem, TRUE);
            return TRUE;
        }

        int nMaxItemGPValue = StringToInt(Get2DAString("skillvsitemcost", "DeviceCostMax", nIdentifySkillRank));

        SetIdentified(oItem, TRUE);
        bIdentified = GetGoldPieceValue(oItem) <= nMaxItemGPValue;
        SetIdentified(oItem, bIdentified);
    }

    return bIdentified;
}

void Examine_SetData(object oPlayer, int nToken, object oTarget, int nPanel)
{
    Examine_SetGenericData(oPlayer, nToken, oTarget, nPanel);

    if (nPanel == GUI_PANEL_EXAMINE_ITEM)
        Examine_SetItemData(oPlayer, nToken, oTarget);
}

void Examine_SetGenericData(object oPlayer, int nToken, object oTarget, int nPanel)
{
    string sTitle, sDescription;
    json jImage1, jImage2, jImage3;
    int bComplexItem = FALSE;
    switch (nPanel)
    {
        case GUI_PANEL_EXAMINE_CREATURE:
        case GUI_PANEL_EXAMINE_PLACEABLE:
        case GUI_PANEL_EXAMINE_DOOR:
        {
            sTitle = GetName(oTarget);
            jImage1 = JsonString(GetPortraitResRef(oTarget) + "m");
            sDescription = GetDescription(oTarget);
            break;
        }

        case GUI_PANEL_EXAMINE_ITEM:
        {
            int bIdentified = Examine_HandleIdentifyItem(oPlayer, oTarget);
            int nBaseItemType = GetBaseItemType(oTarget);
            sTitle = Util_GetItemName(oTarget, bIdentified);

            json jItem = ObjectToJson(oTarget);
            json jComplexIconData = Util_GetComplexIconData(jItem, nBaseItemType);

            if (JsonGetType(jComplexIconData))
            {
                jImage1 = JsonObjectGet(jComplexIconData, "bottom");
                jImage2 = JsonObjectGet(jComplexIconData, "middle");
                jImage3 = JsonObjectGet(jComplexIconData, "top");
                bComplexItem = TRUE;
            }
            else
            {
                jImage1 = JsonString(Util_GetIconResref(oTarget, jItem, nBaseItemType));
            }

            sDescription = GetDescription(oTarget, FALSE, bIdentified);

            int nStatsStrRef = StringToInt(Get2DAString("baseitems", "BaseItemStatRef", nBaseItemType));
            if (nStatsStrRef)
            {
                sDescription += "\n\n" + GetStringByStrRef(nStatsStrRef);
            }
            break;
        }
    }

    NuiSetBind(oPlayer, nToken, NUI_WINDOW_TITLE_BIND, JsonString(sTitle));
    NuiSetBind(oPlayer, nToken, "image_1", jImage1);

    if (bComplexItem)
    {
        NuiSetBind(oPlayer, nToken, "image_2", jImage2);
        NuiSetBind(oPlayer, nToken, "image_3", jImage3);
    }

    NuiSetBind(oPlayer, nToken, "complex_item", JsonBool(bComplexItem));
    NuiSetBind(oPlayer, nToken, "description", JsonString(sDescription));
}

string Examine_GetItemPropertyString(itemproperty ip)
{
    int nType = GetItemPropertyType(ip);
    string sName = GetStringByStrRef(StringToInt(Get2DAString("itempropdef", "GameStrRef", nType)));

    int nSubType = GetItemPropertySubType(ip);
    if(nSubType != -1)
    {
        string sSubTypeResRef = Get2DAString("itempropdef", "SubTypeResRef", nType);
        int nStrRef = StringToInt(Get2DAString(sSubTypeResRef, "Name", nSubType));
        if(nStrRef)
            sName += " " + GetStringByStrRef(nStrRef);
    }

    int nParam1 = GetItemPropertyParam1(ip);
    if(nParam1 != -1)
    {
        string sParamResRef = Get2DAString("iprp_paramtable", "TableResRef", nParam1);
        string sSubTypeResRef = Get2DAString("itempropdef", "SubTypeResRef", nType);
        string sTableResRef = Get2DAString(sSubTypeResRef, "TableResRef", nParam1);
        int nStrRef = StringToInt(Get2DAString(sParamResRef, "Name", GetItemPropertyParam1Value(ip)));
        if(nStrRef)
            sName += " " + GetStringByStrRef(nStrRef);
    }

    int nCostTable = GetItemPropertyCostTable(ip);
    if(nCostTable != -1)
    {
        string sCostTableResRef = Get2DAString("iprp_costtable", "Name", nCostTable);
        int nStrRef = StringToInt(Get2DAString(sCostTableResRef, "Name", GetItemPropertyCostTableValue(ip)));
        if(nStrRef)
            sName += " " + GetStringByStrRef(nStrRef);
    }

    return sName;
}

void Examine_SetItemData(object oPlayer, int nToken, object oItem)
{
    int bIdentified = GetIdentified(oItem);
    json jProperties = JsonArray();
    json jColors = JsonArray();

    if (bIdentified)
    {
        itemproperty ip = GetFirstItemProperty(oItem);
        while (GetIsItemPropertyValid(ip))
        {
            jProperties = JsonArrayInsert(jProperties, JsonString(Examine_GetItemPropertyString(ip)));
            jColors = JsonArrayInsert(jColors, GetItemPropertyDurationType(ip) == DURATION_TYPE_TEMPORARY ? NuiColor(0, 0, 255) : NuiColor(255, 255, 255));
            ip = GetNextItemProperty(oItem);
        }
    }

    NuiSetBind(oPlayer, nToken, "property", jProperties);
    NuiSetBind(oPlayer, nToken, "color", jColors);
}