﻿using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

using CommandParser;

public class CMD
{
    public static void Clear()
    {
        ConsoleManager.Instance.Clear();
    }

    public static void Help()
    {
        ConsoleManager.Instance.Write("To start a static function call, type like this:");
        ConsoleManager.Instance.Write("Namespace.Class.Function(int float bool, string)");
        ConsoleManager.Instance.Write("Then press enter twice to submit your command.");
        ConsoleManager.Instance.WriteEmptyLine();
        ConsoleManager.Instance.Write("Build-in commands: \nCMD.Clear()\nCMD.Help()\nCMD.Add(int, int)\nCMD.Add(string, string)");
        ConsoleManager.Instance.WriteEmptyLine();
    }

    public static int Add(int a, int b)
    {
        return a + b;
    }

    public static string Add(string a, string b)
    {
        return a + b;
    }
}

public class ConsoleManager : MonoBehaviour
{
    public static ConsoleManager Instance { get; private set; }

    public bool logToDebug = false;

    public Text logText;

    public ScrollRect scrollRect;

    public InputField inputField;

	void Awake () 
    {
	    if(Instance == null)
            Instance = this;
	}

    public void SubmitCommand()
    {
        Execute(inputField.text);
        inputField.text = "";
    }

    public void Write(string msg)
    {
        logText.text += msg + "\n";
        if (logToDebug)
            Debug.Log(msg);
    }

    public void WriteEmptyLine()
    {
        logText.text += "\n";
    }

    public void WriteSpliterLine()
    {
        logText.text += "==============================\n";
    }

    public void Execute(string cmd)
    {
        try
        {
            List<Token> tokens = Lexer.Analysis(cmd);

            string str_func;
            string str_namespace;
            List<object> arg_list;

            Parser.Parse(tokens, out str_namespace, out str_func, out arg_list);

            Assembly asb = Assembly.GetExecutingAssembly();
            Type tp = asb.GetType(str_namespace, true);

            object returnValue = tp.InvokeMember(str_func, BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, arg_list.ToArray());

            WriteSpliterLine();
            Write(cmd);
            Write("[Status: Success]");

            if (returnValue != null)
                Write("[Return: " + returnValue.ToString() + "]");
        }
        catch (Exception exp)
        {
            Write("[Error Message: " + exp.Message + "]");
        }
        WriteSpliterLine();
    }

    public void Clear()
    {
        logText.text = "";
    }
}
