/*
	Actiona
	Copyright (C) 2008-2015 Jonathan Mercier-Ganady

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

	Actiona 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program. If not, see <http://www.gnu.org/licenses/>.

	Contact : jmgr@jmgr.info
*/

#ifndef VARIABLECONDITIONINSTANCE_H
#define VARIABLECONDITIONINSTANCE_H

#include "actioninstance.h"
#include "ifactionvalue.h"
#include "code/codeclass.h"
#include "code/rect.h"
#include "code/point.h"

namespace Actions
{
	class VariableConditionInstance : public ActionTools::ActionInstance
	{
		Q_OBJECT
		Q_ENUMS(Comparison)

	public:
		enum Comparison
		{
			Equal,
			Different,
			Inferior,
			Superior,
			InferiorEqual,
			SuperiorEqual,
			Contains
		};

		VariableConditionInstance(const ActionTools::ActionDefinition *definition, QObject *parent = 0)
			: ActionTools::ActionInstance(definition, parent)										{}

		void startExecution()
		{
			bool ok = true;

			QString variableName = evaluateVariable(ok, "variable");
			Comparison comparison = evaluateListElement<Comparison>(ok, comparisons, "comparison");
            QScriptValue value = evaluateValue(ok, "value");
			ActionTools::IfActionValue ifEqual = evaluateIfAction(ok, "ifEqual");
			ActionTools::IfActionValue ifDifferent = evaluateIfAction(ok, "ifDifferent");

			if(!ok)
				return;

            QScriptValue variableValue = variable(variableName);

            if(!variableValue.isValid())
            {
                setCurrentParameter("variable");
                emit executionException(ActionTools::ActionException::InvalidParameterException, tr("Invalid variable"));

                return;
            }

            bool hasResult = false;
            bool result = false;

            if(comparison == Contains)
            {
                if(variableValue.isQObject())
                {
                    QObject *variableObject = variableValue.toQObject();

                    Code::Rect *rectObject = qobject_cast<Code::Rect*>(variableObject);
                    Code::Point *pointObject = qobject_cast<Code::Point*>(value.toQObject());
                    if(rectObject && pointObject)
                    {
                        result = rectObject->rect().contains(pointObject->point());

                        hasResult = true;
                    }
                }
                else if(variableValue.isString())
                {
                    result = variableValue.toString().contains(value.toString());

                    hasResult = true;
                }
                else if(variableValue.isArray())
                {
                    int arrayLength = variableValue.property("length").toInteger();

                    result = false;
                    hasResult = true;

                    for(int arrayIndex = 0; arrayIndex < arrayLength; ++arrayIndex)
                    {
                        if(variableValue.property(arrayIndex).toString() == value.toString())
                        {
                            result = true;

                            break;
                        }
                    }
                }
            }

            if(!hasResult)
            {
                switch(comparison)
                {
                case Equal:
                    result = (variableValue.equals(value));
                    break;
                case Different:
                    result = (!variableValue.equals(value));
                    break;
                case Inferior:
                    result = (variableValue.lessThan(value));
                    break;
                case Superior:
                    result = (!variableValue.lessThan(value) && !variableValue.equals(value));
                    break;
                case InferiorEqual:
                    result = (variableValue.lessThan(value) || variableValue.equals(value));
                    break;
                case SuperiorEqual:
                    result = (!variableValue.lessThan(value));
                    break;
                default:
                    result = false;
                    break;
                }
            }

            QString action = (result ? ifEqual.action() : ifDifferent.action());
            const ActionTools::SubParameter &actionParameter = (result ? ifEqual.actionParameter() : ifDifferent.actionParameter());
			QString line = evaluateSubParameter(ok, actionParameter);

			if(!ok)
				return;

			if(action == ActionTools::IfActionValue::GOTO)
				setNextLine(line);
			else if(action == ActionTools::IfActionValue::CALLPROCEDURE)
			{
				if(!callProcedure(line))
					return;
			}

			emit executionEnded();
		}

		static ActionTools::StringListPair comparisons;

	private:
		Q_DISABLE_COPY(VariableConditionInstance)
	};
}

#endif // VARIABLECONDITIONINSTANCE_H
