using System;
using System.Linq;
using HutongGames.PlayMaker;
using UnityEngine;

namespace BansheeGz.BGDatabase
{
    [ActionCategory("BansheeGz")]
    [HutongGames.PlayMaker.Tooltip("Reset rows values to default values for provided row")]
    public class BGPlaymakerResetValuesRow : BGPlaymakerResetValuesTableBasedA
    {
        public enum RowSourceEnum
        {
            rowIndex,
            rowName,
            rowId
        }

        [HutongGames.PlayMaker.Tooltip("How entity should be retrieved, " +
                                       "rowIndex - 'RowIndex' field will be used to retrieve row by its index, " +
                                       "rowName - 'RowName' field will be used to retrieve row by its name, " +
                                       "rowId - 'RowId' field will be used to retrieve row by its ID")]
        [ObjectType(typeof(RowSourceEnum))]
        public FsmEnum rowSource;

        [HutongGames.PlayMaker.Tooltip("rowIndex to be used for row retrieval if rowSource=RowIndex, otherwise it's ignored")]
        public FsmInt rowIndex;

        [HutongGames.PlayMaker.Tooltip("rowName to be used for row retrieval if rowSource=RowName, otherwise it's ignored")]
        public FsmString rowName;

        [HutongGames.PlayMaker.Tooltip("rowId to be used for row retrieval if rowSource=RowId, otherwise it's ignored")]
        public FsmString rowId;

        [HutongGames.PlayMaker.Tooltip("If this parameter is set to true and default row is not found, exception will not be thrown")]
        public FsmBool noErrorIfRowNotFound;

        public override void Reset()
        {
            base.Reset();
            rowSource = null;
            rowId = null;
            rowName = null;
            rowIndex = null;
            noErrorIfRowNotFound = null;
        }

        public override void OnEnter()
        {
            try
            {
                var meta = Meta;
                var fields = GetFields(meta);

                var defaultMeta = GetDefaultMeta(meta);
                var defaultFields = GetDefaultFields(defaultMeta, fields);

                BGEntity entity = null;
                switch ((RowSourceEnum)rowSource.Value)
                {
                    case RowSourceEnum.rowIndex:
                        entity = meta.GetEntity(rowIndex.Value);
                        break;
                    case RowSourceEnum.rowName:
                        entity = meta.GetEntity(rowName.Value);
                        break;
                    case RowSourceEnum.rowId:
                        entity = meta.GetEntity(new BGId(rowId.Value));
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }

                if (entity == null)
                {
                    switch ((RowSourceEnum)rowSource.Value)
                    {
                        case RowSourceEnum.rowIndex:
                            throw new Exception($"Can not find an entity with index {rowIndex.Value}");
                        case RowSourceEnum.rowName:
                            throw new Exception($"Can not find an entity with name {rowName.Value}");
                        case RowSourceEnum.rowId:
                            throw new Exception($"Can not find an entity with id {rowId.Value}");
                        default:
                            throw new ArgumentOutOfRangeException(nameof(rowSource.Value));
                    }
                }

                var defaultEntity = GetDefaultEntity(defaultMeta, entity, !IsOn(noErrorIfRowNotFound));
                if (defaultEntity != null)
                {
                    Copy(defaultEntity, defaultFields, entity, fields);
                    foreach (var field in fields) field.FireValueChanged(entity);
                    DebugMessage($"{fields.Count} field values are reverted, entity id={entity.Id}, entity name={entity.Name}");
                }
                else DebugMessage($"Entity is not found in default repo. Entity id={entity.Id}, name={entity.Name}");
            }
            catch (Exception e)
            {
                Debug.LogException(e);
                throw;
            }

            Finish();
        }
    }
}