package de.hamsterhobel.jira.internal.modules;

import java.util.ArrayList;

import javax.naming.ConfigurationException;

import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;

import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.exceptions.UnirestException;

import de.hamsterhobel.jira.internal.Connection;
import de.hamsterhobel.jira.internal.Constants;
import de.hamsterhobel.jira.internal.data.JiraTransition;
import de.hamsterhobel.jira.internal.util.JsonParser;

/**
 * Implementation of the Jira API /rest/api/2/issue client.
 * 
 * @see de.hamsterhobel.jira.lib.modules.Issue
 * 
 *      Test: {@link IssueTest}
 * 
 * @author Thomas Irgang
 *
 */
public class Issue implements de.hamsterhobel.jira.lib.modules.Issue {
	private static final Logger log = Logger.getLogger(Issue.class);

	/**
	 * Reference to used {@link de.hamsterhobel.jira.lib.Connection}
	 */
	private final Connection connection;

	/**
	 * Create a new {@link Issue} instance.
	 * 
	 * @param connection
	 *            used {@link de.hamsterhobel.jira.lib.Connection} object
	 * @throws ConfigurationException
	 *             if given connection is null
	 */
	public Issue(Connection connection) throws ConfigurationException {
		super();

		if (connection == null) {
			throw new ConfigurationException("A connection is required!");
		}

		this.connection = connection;
	}

	/**
	 * @see de.hamsterhobel.jira.lib.modules.Issue#issue(String)
	 */
	@Override
	public de.hamsterhobel.jira.lib.data.Issue issue(String id) {
		log.debug("issue");

		de.hamsterhobel.jira.lib.data.Issue issue = null;

		try {
			HttpResponse<JsonNode> response = connection.get(Constants.PATH_ISSUE + "/" + id).asJson();
			if (response.getStatus() == Constants.STATUS_OK) {
				issue = JsonParser.parseIssue(response.getBody().getObject());
			}
		} catch (ConfigurationException | UnirestException e) {
			log.error("issue: " + e.getMessage(), e);
		}

		return issue;
	}

	/**
	 * @see de.hamsterhobel.jira.lib.modules.Issue#assign(String, String)
	 */
	@Override
	public boolean assign(String id, String user) {
		log.debug("assign");

		boolean success = false;
		try {
			JSONObject body = new JSONObject();
			body.put("name", user);
			HttpResponse<String> response = connection.put(Constants.PATH_ISSUE + "/" + id + "/assignee")
					.header(Constants.CONTENT_TYPE_KEY, Constants.CONTENT_TYPE_JSON).body(body).asString();
			if (response.getStatus() == Constants.STATUS_SUCCESS) {
				success = true;
			} else {
				log.debug("assign: failed! (" + response.getStatus() + ") " + response.getBody());
				success = false;
			}
		} catch (ConfigurationException | UnirestException e) {
			log.error("assign: " + e.getMessage(), e);
		}

		return success;
	}

	/**
	 * @see de.hamsterhobel.jira.lib.modules.Issue#transitions(String)
	 */
	@Override
	public ArrayList<JiraTransition> transitions(String id) {
		log.debug("transitions");

		ArrayList<JiraTransition> transitions = null;

		try {
			HttpResponse<JsonNode> response = connection.get(Constants.PATH_ISSUE + "/" + id + "/transitions").asJson();
			if (response.getStatus() == Constants.STATUS_OK) {
				transitions = new ArrayList<>();

				JSONObject jtransition = response.getBody().getObject();
				JSONArray jtransitions = jtransition.getJSONArray("transitions");
				for (int i = 0; i < jtransitions.length(); i++) {
					transitions.add(JsonParser.parseTransition(jtransitions.getJSONObject(i)));
				}
			}
		} catch (ConfigurationException | UnirestException e) {
			log.error("transitions: " + e.getMessage(), e);
		}

		return transitions;
	}
}
