﻿// Copyright 2013-2022 AFI,Inc. All rights reserved

using System;
using System.Collections.Generic;
using System.Text;
using BackEnd;
using LitJson;
using UnityEngine;

// 뒤끝 기능 함수의 부모 객체
public abstract class BaseGroup : MonoBehaviour {
    
    // 싱글톤으로 UIManager를 통해 가져오기에는
    // 코드가 너무 길어지고 해당 클래스에서만 사용하므로 분리.
    protected UI_RequestUI requestUI;

    // UIManager -> UI_MainFunction에서 세팅받고 UI_MainFunctionButton에 할당됨
    public void Initialize(UI_RequestUI requestUIMember) {
        requestUI = requestUIMember;
    }
    
    // 각 클래스마다 메인 함수의 이름을 구성해야함.
    public abstract string GetGroupName();
    
    // 각 클래스마다 버튼 클릭 시, 관련 함수들이 서브 버튼으로 생성되도록 구성해야함. 
    public abstract void SetSubFunctionButton();

    protected void ShowResultData(BackendReturnObject bro) {
        if (bro.IsSuccess() == false) {
            UIManager.Instance.OpenResultUI(bro.ToString());
            return;
        }

        if (bro.GetStatusCode() != "200") {
            UIManager.Instance.OpenResultUI(bro.ToString());
            return;
        }

        StringBuilder stringBuilder = new StringBuilder();

        if (bro.GetReturnValuetoJSON() == null) {
            UIManager.Instance.OpenResultUI(bro.ToString());
            return;
        }
        
        AppendJsonDataToString(bro.GetFlattenJSON(), stringBuilder, "| ");
        
        UIManager.Instance.OpenResultUI(stringBuilder.ToString());
    }
    
    protected void ShowResultData(JsonData json) {

        StringBuilder stringBuilder = new StringBuilder();
        AppendJsonDataToString(json, stringBuilder, "| ");
        
        UIManager.Instance.OpenResultUI(stringBuilder.ToString());
    }

    private void AppendJsonDataToString(JsonData originalJson, StringBuilder builder, string startString) {
        startString = " " + startString;
        try {
            if (originalJson.IsArray) {
                if(originalJson.Count <= 0) {
                    builder.AppendLine();
                    builder.Append(startString + "데이터가 존재하지 않음");
                }

                for(int i = 0; i < originalJson.Count; i++) {
                    builder.AppendLine();
                    builder.Append(startString + (i+1) + "번째");
                    AppendJsonDataToString(originalJson[i], builder, startString);
                    builder.AppendLine();

                }
            }
            else if (originalJson.IsObject) {
                foreach (string key in originalJson.Keys) {
                    builder.AppendLine();
                    builder.Append(startString + key.ToString());
                    if(originalJson[key] == null) {
                        builder.Append(" : " + "null");
                    }
                    else {
                        AppendJsonDataToString(originalJson[key], builder, startString);
                    }
                }
            }
            else {
                builder.Append(" : " + originalJson?.ToString());
            }
				
        }
        catch (Exception e) {
            builder.AppendLine();
            builder.AppendLine("파싱 도중 에러가 발생했습니다.");
            builder.AppendLine(e.ToString());
        }
    }

    protected void Alert(string alertText) {
        AlertUI.Instance.OpenUI(alertText);
    }

    protected string InputParseByString(int inputFieldIndex, int inputFieldColumnIndex) {

        return requestUI.GetValueInputFieldList()[inputFieldIndex].GetInputFields(inputFieldColumnIndex);
    }
    
    protected string InputParseByStringWithSpecialChar(int inputFieldIndex, int inputFieldColumnIndex) {

        return requestUI.GetValueInputFieldList()[inputFieldIndex].GetInputFields(inputFieldColumnIndex,false);
    }
    
    protected int InputParseByInt(int inputFieldIndex, int inputFieldColumnIndex, bool isAlert = true) {

        string inputValue = requestUI.GetValueInputFieldList()[inputFieldIndex].GetInputFields(inputFieldColumnIndex);

        if (int.TryParse(inputValue, out var value) == false) {
            throw new Exception($"\n입력하신 항목 중 {inputFieldIndex + 1}번째 값\n'{inputValue}'을 {value.GetType()}로 변환하는 것이 불가능합니다.\n");
            
        }

        return value;
    }
    
    protected float InputParseByFloat(int inputFieldIndex, int inputFieldColumnIndex) {

        string inputValue = requestUI.GetValueInputFieldList()[inputFieldIndex].GetInputFields(inputFieldColumnIndex);

        if (float.TryParse(inputValue, out var value) == false) {
            throw new Exception($"\n입력하신 항목 중 {inputFieldIndex + 1}번째 값\n'{inputValue}'을 {value.GetType()}로 변환하는 것이 불가능합니다.\n");
        }

        return value;
    }
    
    protected bool InputParseByBool(int inputFieldIndex, int inputFieldColumnIndex, bool isAlert = true) {
        
        string inputValue = requestUI.GetValueInputFieldList()[inputFieldIndex].GetInputFields(inputFieldColumnIndex);

        if (bool.TryParse(inputValue, out var value) == false) {
            throw new Exception($"\n입력하신 항목 중 {inputFieldIndex + 1}번째 값\n'{inputValue}'을 {value.GetType()}로 변환하는 것이 불가능합니다.\n");
        }

        return value;
    }


    protected T InputParseByEnum<T>(int inputFieldIndex, int inputFieldColumnIndex, bool isAlert = true) where T : struct, Enum {

        string inputValue = requestUI.GetValueInputFieldList()[inputFieldIndex].GetInputFields(inputFieldColumnIndex);

        if (Enum.TryParse<T>(inputValue, out T value) == false) {
            throw new Exception($"\n입력하신 항목 중 {inputFieldIndex + 1}번째 값\n'{inputValue}'을 {value.GetType()}로 변환하는 것이 불가능합니다.\n");
        }

        return value;
    }

    protected void AddParamFromExtraInput(int startIndex, Param param) {
        Dictionary<string, List<string>> listDictionary = new Dictionary<string, List<string>>();
        Dictionary<string, Dictionary<string, string>> dictionaryDictionary = new Dictionary<string, Dictionary<string, string>>();

        for (int i = startIndex; i <  requestUI.GetValueInputFieldList().Count; i++) {
            switch (requestUI.GetValueInputFieldList()[i].dataType) {
                case DataType.NORMAL:
                    var columnName = InputParseByString(i, 0);

                    try {
                        float numberValue = InputParseByFloat(i, 1);
                        param.Add(columnName, numberValue);

                    } catch (Exception) {
                        var columnValue = InputParseByString(i, 1);
                        param.Add(columnName, columnValue);
                    }
                    break;

                case DataType.LIST:
                    var listName = InputParseByString(i, 0);
                    var listValue = InputParseByString(i, 1);

                    if (listDictionary.ContainsKey(listName) == false) {
                        listDictionary.Add(listName, new List<string>());
                    }

                    listDictionary[listName].Add(listValue);
                    break;

                case DataType.DICTIONARY:
                    var dictionaryName = InputParseByString(i, 0);
                    var dictionaryKey = InputParseByString(i, 1);
                    var dictionaryValue = InputParseByString(i, 2);

                    if (dictionaryDictionary.ContainsKey(dictionaryName) == false) {
                        dictionaryDictionary.Add(dictionaryName, new Dictionary<string, string>());
                    }

                    if (dictionaryDictionary[dictionaryName].ContainsKey(dictionaryKey)) {
                        throw new Exception($"딕셔너리에 이미 {dictionaryKey} 키 값을 가진 데이터가 존재합니다.");
                    }

                    dictionaryDictionary[dictionaryName].Add(dictionaryKey, dictionaryValue );
                    break;

                default:
                    throw new Exception($"{i}번째 입력값은 정의되지 않은 입력값입니다.");
            }
        }


        foreach (var list in listDictionary) {
            param.Add(list.Key, list.Value);
        }

        foreach (var dic in dictionaryDictionary) {
            param.Add(dic.Key, dic.Value);
        }
    }
}
