/* 
-*- coding: latin-1 -*-

This file is part of RefactorErl.

RefactorErl is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

RefactorErl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with RefactorErl.  If not, see <http://plc.inf.elte.hu/erlang/>.

The Original Code is RefactorErl.

The Initial Developer of the Original Code is Eötvös Loránd University.
Portions created  by Eötvös Loránd University and ELTE-Soft Ltd.
are Copyright 2007-2025 Eötvös Loránd University, ELTE-Soft Ltd.
and Ericsson Hungary. All Rights Reserved.
*/

package com.refactorerl.ui.communication;

import java.util.HashMap;
import java.util.Map;

import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangList;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangString;
import com.ericsson.otp.erlang.OtpErlangTuple;
import com.refactorerl.ui.common.OtpErlangHelper;

/**
 * This contains methods to simplify the parsing of the reply, change, progress,
 * job info messages sent by RefactorErl.
 * 
 * @author Daniel Lukacs, 2014 ELTE IK
 *
 */
public class MessageParseHelper {

	static public OtpErlangObject getBody(OtpErlangObject msg) {
		return OtpErlangHelper.nth(msg, 2);
	}

	static public String getType(OtpErlangObject msg) {
		return OtpErlangHelper.nth(msg, 1).toString();
	}

	static public OtpErlangObject getHeader(OtpErlangObject msg) {
		return OtpErlangHelper.nth(msg, 0);
	}

	static public boolean isBodyOK(OtpErlangObject msg) {
		return OtpErlangHelper.nth(getBody(msg), 0).equals(
				new OtpErlangAtom("ok")); //$NON-NLS-1$
	}

	static public boolean isBodyAborted(OtpErlangObject msg) {
		OtpErlangObject msgData = OtpErlangHelper.nth(getBody(msg), 1);
		return OtpErlangHelper.nth(msgData, 0).equals(
				new OtpErlangAtom("abort")); //$NON-NLS-1$

	}

	static public double parseProgressTaskPercent(OtpErlangObject msg) {
		try {

			double progress = 0;
			if (parseIsProgressCompleted(msg))
				progress = 1.0;
			else {
				int current = parseProgressCurrentUnit(msg);
				int all = parseProgressAllUnit(msg);
				progress = current / (double) all;
			}
			return Math.round(progress * 100.0) / 100.0;

		} catch (ClassCastException e) {

			throw new IllegalArgumentException(OtpErlangHelper.nth(
					getBody(msg), 3).toString()
					+ "/" //$NON-NLS-1$
					+ OtpErlangHelper.nth(getBody(msg), 4) + " " //$NON-NLS-1$
					+ msg.toString() + " " + e.getClass()); //$NON-NLS-1$
		}
	}

	static public boolean parseIsProgressCompleted(OtpErlangObject msg) {
		return OtpErlangHelper.nthEqualsAtom(getBody(msg), 0, "completed"); //$NON-NLS-1$
	}

	static public int parseProgressAllUnit(OtpErlangObject msg) {
		return Integer
				.parseInt(OtpErlangHelper.nth(getBody(msg), 4).toString());
	}

	static public int parseProgressCurrentUnit(OtpErlangObject msg) {
		int current = Integer.parseInt(OtpErlangHelper.nth(getBody(msg), 3)
				.toString());
		return current;
	}

	static public double parseProgressPercent(OtpErlangObject msg) {
		double current = Double.parseDouble(OtpErlangHelper
				.nth(getBody(msg), 2).toString());
		return current;
	}

	static public String parseProgressTaskInfo(OtpErlangObject msg) {
		String task = OtpErlangHelper.toUnquotedString(OtpErlangHelper.nth(
				getBody(msg), 0));
		if (task == "completed")return Messages.MessageParseHelper_7; //$NON-NLS-1$
		String file = OtpErlangHelper.toUnquotedString(OtpErlangHelper.nth(
				getBody(msg), 1));
		return Messages.MessageParseHelper_8 + task
				+ Messages.MessageParseHelper_9 + file;
	}

	static public StatusChangeMessage parseChanges2(Object o) {
		if (!(o instanceof OtpErlangObject))
			return null;
		OtpErlangObject msg = (OtpErlangObject) o;

		if (!getType(msg).equals("statusinfo") //$NON-NLS-1$
				|| !OtpErlangHelper.nthEqualsAtom(
						OtpErlangHelper.nth(getBody(msg), 0), 0, "change")) //$NON-NLS-1$
			return null;

		try {

			// [{changes ...
			OtpErlangObject[] ls = ((OtpErlangList) getBody(msg)).elements();

			// [{FilePath ...
			OtpErlangObject[] ls2 = ((OtpErlangList) OtpErlangHelper.nth(ls[0],
					1)).elements();

			String filePath = ((OtpErlangString) OtpErlangHelper.nth(ls2[0], 0))
					.stringValue();

			// [{present ...
			OtpErlangObject[] ls3 = ((OtpErlangList) OtpErlangHelper.nth(
					ls2[0], 1)).elements();

			// present | rename | content | error
			String key = ((OtpErlangAtom) OtpErlangHelper.nth(ls3[0], 0))
					.toString();

			OtpErlangObject valueOtp = OtpErlangHelper.nth(ls3[0], 1);

			if (key.equals("present") || key.equals("content")) { //$NON-NLS-1$ //$NON-NLS-2$
				return new StatusChangeMessage<Boolean>(filePath, key,
						OtpErlangHelper.equalsAtom(valueOtp, "true")); //$NON-NLS-1$
			} else if (key.equals("rename") || key.equals("error")) { //$NON-NLS-1$ //$NON-NLS-2$
				return new StatusChangeMessage<String>(filePath, key,
						OtpErlangHelper.toUnquotedString(valueOtp));
			} else {
				return null;
			}

		} catch (ClassCastException e) {
			return null;
		}

	}

	@Deprecated
	static public Map<String, Boolean> parseChanges(Object o) {
		if (!(o instanceof OtpErlangObject))
			return null;
		OtpErlangObject msg = (OtpErlangObject) o;

		if (!getType(msg).equals("statusinfo") //$NON-NLS-1$
				|| !OtpErlangHelper.nthEqualsAtom(
						OtpErlangHelper.nth(getBody(msg), 0), 0, "change")) //$NON-NLS-1$
			return null;

		try {
			Map<String, Boolean> changes = new HashMap<>();

			OtpErlangObject[] ls = ((OtpErlangList) getBody(msg)).elements();
			for (OtpErlangObject t : ls) {
				OtpErlangObject[] ls2 = ((OtpErlangList) OtpErlangHelper.nth(t,
						1)).elements();
				for (OtpErlangObject u : ls2) {
					String filename = ((OtpErlangString) OtpErlangHelper.nth(u,
							0)).stringValue();
					OtpErlangObject present = OtpErlangHelper.nth(
							OtpErlangHelper.nth(OtpErlangHelper.nth(u, 1), 0),
							1);

					boolean b;
					if (OtpErlangHelper.equalsAtom(present, "true")) //$NON-NLS-1$
						b = true;
					else if (OtpErlangHelper.equalsAtom(present, "false")) //$NON-NLS-1$
						b = false;
					else
						throw new IllegalArgumentException();

					changes.put(filename, b);
				}
			}
			return changes;

		} catch (ClassCastException e) {
			return null;
		}
	}

	static public JobInfoMessage parseJobInfo(Object o) {
		JobInfoMessage result = null;

		if (!(o instanceof OtpErlangObject))
			throw new IllegalArgumentException(Messages.MessageParseHelper_21);
		OtpErlangObject msg = (OtpErlangObject) o;

		if (!getType(msg).equals("jobinfo")) //$NON-NLS-1$
			throw new IllegalArgumentException(Messages.MessageParseHelper_23
					+ msg.toString());

		try {
			String info = OtpErlangHelper.nth(getBody(msg), 1).toString();
			OtpErlangTuple tuple = (OtpErlangTuple) OtpErlangHelper.nth(
					getBody(msg), 0);
			String jobName = OtpErlangHelper.nth(tuple, 0).toString();
			boolean modifier = OtpErlangHelper.nthEqualsAtom(tuple, 1,
					"modifier"); //$NON-NLS-1$
			JobInfoMessage.Status status = null;
			if (OtpErlangHelper.nthEqualsAtom(tuple, 2, "finished")) //$NON-NLS-1$
				status = JobInfoMessage.Status.FINISHED;
			else if (OtpErlangHelper.nthEqualsAtom(tuple, 2, "started")) //$NON-NLS-1$
				status = JobInfoMessage.Status.STARTED;

			OtpErlangObject content = OtpErlangHelper.nth(tuple, 3);

			result = new JobInfoMessage(msg, jobName, modifier, status,
					content, info);

		} catch (ClassCastException e) {
			throw new IllegalArgumentException(Messages.MessageParseHelper_27
					+ msg.toString());
		}

		return result;
	}
}
