/* 
-*- 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.logic.dupcode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangList;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangTuple;
import com.refactorerl.ui.common.OtpErlangHelper;
import com.refactorerl.ui.communication.MessageParseHelper;
import com.refactorerl.ui.communication.ReferlProxy;
import com.refactorerl.ui.communication.exceptions.RequestException;
import com.refactorerl.ui.logic.AbstractRequest;

public class GetAlgorithmDataRequest extends AbstractRequest<List<AlgorithmData>> {

	final Map<String, AlgorithmData.DataType> dataTypes = new HashMap<>();
	{
		dataTypes.put("enum", AlgorithmData.DataType.ENUM); //$NON-NLS-1$
		dataTypes.put("atom", AlgorithmData.DataType.ATOM); //$NON-NLS-1$
		dataTypes.put("atoms", AlgorithmData.DataType.ATOMS); //$NON-NLS-1$
		dataTypes.put("integer", AlgorithmData.DataType.INT); //$NON-NLS-1$
		dataTypes.put("float", AlgorithmData.DataType.FLOAT); //$NON-NLS-1$
		dataTypes.put("boolean", AlgorithmData.DataType.BOOL); //$NON-NLS-1$
	}

	final Map<String, AlgorithmData.EnumType> enumTypes = new HashMap<>();

	private OtpErlangTuple request;
	{
		enumTypes.put("string", AlgorithmData.EnumType.STRING); //$NON-NLS-1$
		enumTypes.put("atom", AlgorithmData.EnumType.ATOM); //$NON-NLS-1$
	}

	public GetAlgorithmDataRequest(String key, ReferlProxy proxy, Logger logger) {
		super(proxy, logger);

		request = new OtpErlangTuple(new OtpErlangObject[] { new OtpErlangAtom("get_algorithm_data"), //$NON-NLS-1$
				new OtpErlangAtom(key) });
	}

	@Override
	protected OtpErlangObject doGetRequest() {

		return request;
	}

	@Override
	protected List<AlgorithmData> doProcessReply(OtpErlangObject m) throws RequestException {

		List<AlgorithmData> algDatas = new ArrayList<>();
		OtpErlangList otpAlgDatas = (OtpErlangList) OtpErlangHelper.nth(MessageParseHelper.getBody(m), 1);

		for (OtpErlangObject otpAlgData : otpAlgDatas) {
			algDatas.add(parseOtpAlgData(otpAlgData));
		}

		return algDatas;
	}

	private AlgorithmData parseOtpAlgData(OtpErlangObject otpAlgData) {
		Map<String, OtpErlangObject> propList = OtpErlangHelper.translatePropList(OtpErlangHelper.nth(otpAlgData, 1));

		String key = OtpErlangHelper.toUnquotedString(propList.get("key")); //$NON-NLS-1$
		String label = OtpErlangHelper.toUnquotedString(propList.get("label")); //$NON-NLS-1$
		String defaultValue = OtpErlangHelper.toUnquotedString(propList.get("default")); //$NON-NLS-1$
		String dataType0 = OtpErlangHelper.toUnquotedString(propList.get("type")); //$NON-NLS-1$
		AlgorithmData.DataType dataType = dataTypes.get(dataType0);
		if (dataType.equals(AlgorithmData.DataType.ENUM)) {
			OtpErlangList otpOptions = (OtpErlangList) propList.get("options"); //$NON-NLS-1$
			String[] options = new String[otpOptions.arity()];
			int i = 0;
			for (OtpErlangObject o : otpOptions) {
				options[i] = OtpErlangHelper.toUnquotedString(o);
				++i;
			}
			String enumType0 = OtpErlangHelper.toUnquotedString(propList.get("enumtype")); //$NON-NLS-1$
			AlgorithmData.EnumType enumType = enumTypes.get(enumType0);

			return new AlgorithmData(key, label, dataType, defaultValue, options, enumType);

		}

		return new AlgorithmData(key, label, dataType, defaultValue);
	}

}
