/*
* Licensed Materials - Property of IBM Corp.
* IBM UrbanCode Release
* (c) Copyright IBM Corporation 2011, 2016. All Rights Reserved.
*
* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
* GSA ADP Schedule Contract with IBM Corp.
*/
package com.urbancode.air.plugin.jira;

import java.util.ArrayList;
import java.util.List;

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import com.urbancode.commons.webext.util.JSONUtilities;

public class JiraChange {

    //**********************************************************************************************
    // CLASS
    //**********************************************************************************************

    //**********************************************************************************************
    // INSTANCE
    //**********************************************************************************************
    final private String name;
    final private String description;
    final private String id;
    final private String key;
    final private String typeId;
    final private String typeName;
    final private String statusId;
    final private String statusName;
    final private String priorityId;
    final private String priorityName;
    private String initiativeId;
    private String initiativeName;
    final private List<JiraRelease> releases = new ArrayList<JiraRelease>();
    private String projectName; // Only used for custom field mapping of Application
    private String projectId;   // Only used for custom field mapping of Application

    final static private APPLICATION = "Application"
    final static private INITIATIVE  = "Initiative"
    final static private RELEASE     = "Release"

    //----------------------------------------------------------------------------------------------
    public JiraChange(JSONObject json, HashMap<String, String> customFields) throws JSONException {
        JSONObject fields = JSONUtilities.getJsonObjectFromJsonObject(json, "fields");

        name = (JSONUtilities.getStringFromJsonObject(fields, "summary")?:"").trim();
        if (name.length() > 253) {
            name = name.substring(0, 250) + "..."
        }

        description = JSONUtilities.getStringFromJsonObject(fields, "description");
        id = JSONUtilities.getStringFromJsonObject(json, "id");
        key = JSONUtilities.getStringFromJsonObject(json, "key");
        typeId = JSONUtilities.getStringFromJsonObject(
                JSONUtilities.getJsonObjectFromJsonObject(fields, "issuetype"), "id");
        typeName = (JSONUtilities.getStringFromJsonObject(
                JSONUtilities.getJsonObjectFromJsonObject(fields, "issuetype"), "name")?:"").trim();
        statusId = JSONUtilities.getStringFromJsonObject(
                JSONUtilities.getJsonObjectFromJsonObject(fields, "status"), "id");
        statusName = (JSONUtilities.getStringFromJsonObject(
                JSONUtilities.getJsonObjectFromJsonObject(fields, "status"), "name")?:"").trim();
        try {
            priorityId = JSONUtilities.getStringFromJsonObject(
                    JSONUtilities.getJsonObjectFromJsonObject(fields, "priority"), "id");
            priorityName = (JSONUtilities.getStringFromJsonObject(
                JSONUtilities.getJsonObjectFromJsonObject(fields, "priority"), "name")?:"").trim();
        } catch (NullPointerException ex) {
            // Swallow NullPointerException
            // Likely only on JIRA v7
        }

        // CUSTOM APPLICATION FIELD
        if (customFields.containsKey(APPLICATION)) {
            setCustomValueInit(fields, APPLICATION, customFields.get(APPLICATION))
        }

        // CUSTOM RELEASE FIELD
        // Else Manual Mapping is Used
        if (customFields.containsKey(RELEASE)) {
            setCustomValueInit(fields, RELEASE, customFields.get(RELEASE))
        }

        // CUSTOM INITIATIVE FIELD
        if (customFields.containsKey(INITIATIVE)) {
            setCustomValueInit(fields, INITIATIVE, customFields.get(INITIATIVE))
        }
    }

    //----------------------------------------------------------------------------------------------
    public String getName() {
        return name;
    }

    //----------------------------------------------------------------------------------------------
    public String getDescription() {
        return description;
    }

    //----------------------------------------------------------------------------------------------
    public String getId() {
        return id;
    }

    //----------------------------------------------------------------------------------------------
    public String getKey() {
        return key;
    }

    //----------------------------------------------------------------------------------------------
    public String getTypeId() {
        return typeId;
    }

    //----------------------------------------------------------------------------------------------
    public String getTypeName() {
        return typeName;
    }

    //----------------------------------------------------------------------------------------------
    public String getStatusId() {
        return statusId;
    }

    //----------------------------------------------------------------------------------------------
    public String getStatusName() {
        return statusName;
    }

    //----------------------------------------------------------------------------------------------
    public String getPriorityId() {
        return priorityId;
    }

    //----------------------------------------------------------------------------------------------
    public String getPriorityName() {
        return priorityName;
    }

    //----------------------------------------------------------------------------------------------
    public String getInitiativeName() {
        return initiativeName;
    }

    //----------------------------------------------------------------------------------------------
    public String getInitiativeId() {
        return initiativeId;
    }

    //----------------------------------------------------------------------------------------------
    public List<JiraRelease> getReleases() {
        return releases;
    }

    //----------------------------------------------------------------------------------------------
    public String getProjectName() {
        return projectName;
    }

    //----------------------------------------------------------------------------------------------
    public String getProjectId() {
        return projectId;
    }

    //----------------------------------------------------------------------------------------------
    /**
     * param fields JSONObject containing JIRA Issue Data
     * param customFields HashMap of customField ID and mapped uRelease field
     * @returns Custom Field Release ID and Name are Set
     */
    private void setCustomValueInit(JSONObject fields, String customFieldType, String customFieldId) {
        def customFieldValue = JSONUtilities.getStringFromJsonObject(fields, customFieldId)
        // If Custom Field is null, ignore
        if (customFieldValue) {
            // Multiple Releases in JSONArray
            if (customFieldValue.startsWith("[")) {
                setCustomValue(customFieldType, JSONUtilities.getJsonArrayFromJsonObject(fields, customFieldId))
            }
            // Single Release in JSON
            else if (customFieldValue.startsWith("{")) {
                setCustomValue(customFieldType, JSONUtilities.getJsonObjectFromJsonObject(fields, customFieldId))
            }
            // Single Release in String
            else {
                setCustomValue(customFieldType, customFieldValue)
            }
        }
    }

    //----------------------------------------------------------------------------------------------
    private void setCustomValue(String customFieldType, JSONArray jsonArray) {
        for (int i = 0; i < jsonArray.length(); i++) {
            setCustomValue(customFieldType, jsonArray.getJSONObject(i))
        }
    }

    //----------------------------------------------------------------------------------------------
    private void setCustomValue(String customFieldType, JSONObject jsonObj) {
        def name = JSONUtilities.getStringFromJsonObject(jsonObj, "name")
        // If "name" property doesn't exist, set name as "value" instead
        if (!name) {
            name = JSONUtilities.getStringFromJsonObject(jsonObj, "value")
        }
        def id = JSONUtilities.getStringFromJsonObject(jsonObj, "id")
        setCustomValue(customFieldType, name + ":" + id)
    }

    //----------------------------------------------------------------------------------------------
    private void setCustomValue(String customFieldType, String jsonStr) {
        // Delimit the String by a _ or :
        def temp = jsonStr.split("_|:",2)*.trim()
        def name = temp[0]
        def id = (temp.size() == 2)?temp[1]:temp[0] //Use ID unless empty
        if(customFieldType == APPLICATION) {
            this.projectName = name
            this.projectId = id
        }
        else if(customFieldType == INITIATIVE) {
            this.initiativeName = name
            this.initiativeId = id
        }
        else if (customFieldType == RELEASE) {
            JSONObject obj = new JSONObject("{name:${name}, id:${id}}")
            releases.add(new JiraRelease(obj))
        }
        else {
            throw new Exception("[Error] Unknown ${customFieldType}' customFieldType reached in setCustomValue.")
        }
    }
}
