using System;
using System.Globalization;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Data;
using System.ComponentModel;
using System.Collections.ObjectModel;
using Message;

namespace TMC_Tool
{
  /// <summary>
  /// EditMaterialWindow.xaml の相互作用ロジック
  /// </summary>
  public partial class EditMatecpWindow : Window
  {
    private static Dictionary<string, string> txt = new Dictionary<string, string>();

    private static bool dialogResult;

    private static TMCData tmcData;
    private static TmcTables tmcTables;
    private static CustompTables cpTables;

    SortedSet<uint> paramListData = new SortedSet<uint>();

    private bool IsActivated = false;

    public EditMatecpWindow()
    {
      InitializeComponent();

      this.MouseLeftButtonDown += (sender, e) => this.DragMove();
      this.ShowInTaskbar = false;

      title.Text = txt["editMatecpTitle"];
      btnAdd.Content = txt["Add"];
      btnGet.Content = txt["Get"];
      btnDel.Content = txt["Del"];
      btnAddParam.Content = txt["Add"];
      btnDelParam.Content = txt["Del"];
      labelParams.Content = txt["Parameter"];
      labelInfluenceObj.Content = txt["InfluenceObj"];
      btnOk.Content = txt["OK"];
      btnCancel.Content = txt["Cancel"];
    }

    public static void lang(Dictionary<string, string> langText)
    {
      txt = langText;
    }

    private void btnOk_Click(object sender, RoutedEventArgs e)
    {
      dialogResult = true;
      this.Close();
    }

    private void btnCancel_Click(object sender, RoutedEventArgs e)
    {
      dialogResult = false;
    }

    private void dgCustomps_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
      if (!this.IsInitialized) return;

      if (dgCustomps.SelectedItems.Count > 0)
      {
        listInfluenceObj.Text = "";
        foreach (var obj in tmcTables.ObjData)
        {
          foreach (var item in dgCustomps.SelectedItems)
          {
            var customp = item as CustompTables.CustomParameters;
            if (obj.Matecp == customp.OriginalIndex)
            {
              if (listInfluenceObj.Text != "") listInfluenceObj.Text += "\r\n";
              listInfluenceObj.Text += obj.Name;
            }
          }
        }
        if (listInfluenceObj.Text != "")
          listInfluenceObj.IsEnabled = true;
        else
          listInfluenceObj.IsEnabled = false;

        if (dgCustomps.SelectedItems.Count == 1)
        {
          cpTables.SetParams(cpTables.Customps[dgCustomps.SelectedIndex]);
          if (cpTables.Customps[dgCustomps.SelectedIndex].Use == 0)
            btnDel.IsEnabled = true;
          else
            btnDel.IsEnabled = false;

          paramListBuild();
        }
      }
      if (dgCustomps.SelectedItems.Count != 1)
      {
        if (cpTables.Params.Count != 0) cpTables.Params.Clear();
        cmbParam.IsEnabled = false;
        btnAddParam.IsEnabled = false;
        btnDelParam.IsEnabled = false;
      }
    }

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
      var newCustomp = new CustompTables.CustomParameters(null, 0);
      newCustomp.Index = dgCustomps.Items.Count;
      newCustomp.OriginalIndex = -1;
      var newCp = new CustompParam();
      newCp.Index = 0;
      newCp.Data1 = 0x854D87AE;
      newCp.Data2 = 1;
      newCp.Param = 1;
      newCustomp.cp.Add(newCp);
      newCustomp.Count = 1;
      cpTables.Customps.Add(newCustomp);
      dgCustomps.SelectedIndex = dgCustomps.Items.Count - 1;
      dgCustomps.ScrollIntoView(dgCustomps.Items[dgCustomps.SelectedIndex]);

      btnOk.IsEnabled = true;
    }

    private void btnGet_Click(object sender, RoutedEventArgs e)
    {
      MainWindow mainWindow = this.Owner as MainWindow;
      int selIndex = -1;
      if (dgCustomps.SelectedItems.Count == 1) selIndex = dgCustomps.SelectedIndex;
      GettingMaterial gettingMat = mainWindow.getMaterial("matecp", selIndex);

      if (gettingMat == null || gettingMat.MateCp == null) return;

      bool result = checkGettingMateCp(gettingMat);
      this.Owner.IsEnabled = false;
      if (!result) return;

      if (gettingMat.MateCpAdd)
      {
        gettingMat.MateCp.Index = cpTables.Customps.Count;
        var newCp = new CustompTables.CustomParameters(gettingMat.MateCp, 0);
        newCp.OriginalIndex = -1;
        cpTables.Customps.Add(newCp);
        dgCustomps.SelectedIndex = dgCustomps.Items.Count - 1;
        dgCustomps.ScrollIntoView(dgCustomps.Items[dgCustomps.SelectedIndex]);
      }
      else
      {
        cpTables.Customps[gettingMat.MateCpTarget].cp.Clear();
        foreach (var cp in gettingMat.MateCp.cp)
        {
          cpTables.Customps[gettingMat.MateCpTarget].cp.Add(cp);
        }
        if (selIndex != -1)
        {
          dgCustomps.SelectedIndex = -1;
          dgCustomps.SelectedIndex = selIndex;
        }
      }
      btnOk.IsEnabled = true;
    }

    private void btnDel_Click(object sender, RoutedEventArgs e)
    {
      List<int> selectedIndices = new List<int>();
      foreach (var item in dgCustomps.SelectedItems)
      {
        var customp = item as CustompTables.CustomParameters;
        if (customp.Use == 0) selectedIndices.Add(customp.Index);
      }

      selectedIndices.Sort();
      selectedIndices.Reverse();

      foreach (var index in selectedIndices)
      {
        cpTables.Customps.RemoveAt(index);
      }

      cpTables.ResetCustompIndex();
      btnOk.IsEnabled = true;
    }

    private void dgParams_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
      if (!this.IsInitialized) return;

      if (dgParams.Items.Count > 1)
        btnDelParam.IsEnabled = true;
      else
        btnDelParam.IsEnabled = false;
    }

    private void tbParam_KeyDown(object sender, KeyEventArgs e)
    {
      btnOk.IsEnabled = true;
    }

    private void cmbParam_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
      if (this.IsInitialized && cmbParam.SelectedIndex != -1)
      {
        checkBtnAddParam();
      }
    }

    private void btnAddParam_Click(object sender, RoutedEventArgs e)
    {
      try
      {
        if (cmbParam.SelectedIndex != -1)
        {
          string type = cmbParam.SelectedValue.ToString();
          string uintTxt = type.Substring(2).Split(' ')[0];

          // 排他確認
          var findParams = new List<CustompTables.Parameters>();
          string findText = "";
          foreach (var param in cpTables.Params)
          {
            if (
              (uintTxt == "EB53FEEF" && (param.TypeVal == 0x60121B1E || param.TypeVal == 0xD66548AD)) ||
              ((uintTxt == "60121B1E" || uintTxt == "D66548AD") && param.TypeVal == 0xEB53FEEF)
            )
            {
              findParams.Add(param);
              findText += "\r\n" + param.Type;
            }
          }
          if (findParams.Count > 0)
          {
            string result = MessageWindow.Show(this, txt["ConfirmParamDelAndAdd"] + "\r\n" + findText, txt["Confirm"], txt["DelAndAdd"], txt["No"]);
            if (result == "Cancel")
            {
              return;
            }
            while (findParams.Count > 0)
            {
              cpTables.Params.Remove(findParams[0]);
              findParams.RemoveAt(0);
            }
          }

          CustompTables.Parameters newParam = new CustompTables.Parameters();
          newParam.TypeVal = UInt32.Parse(uintTxt, NumberStyles.AllowHexSpecifier);
          newParam.Type = type;
          cpTables.Params.Add(newParam);

          // ソート
          var tempParams = new ObservableCollection<CustompTables.Parameters>(cpTables.Params.OrderBy(n => n.TypeVal));
          cpTables.Params.Clear();
          foreach (var param in tempParams)
          {
            cpTables.Params.Add(param);
          }

          cpTables.ReflectChangeParams(dgCustomps.SelectedIndex);

          checkBtnAddParam();
          btnOk.IsEnabled = true;
        }
      }
      catch
      {
        return;
      }
        
    }

    private void btnDelParam_Click(object sender, RoutedEventArgs e)
    {
      foreach (var item in dgParams.SelectedItems)
      {
        var param = item as CustompTables.Parameters;
        Console.WriteLine(param.Type);
      }
      while(dgParams.SelectedItems.Count > 0 && dgParams.Items.Count > 1)
      {
        var param = dgParams.SelectedItem as CustompTables.Parameters;
        cpTables.Params.Remove(param);
      }

      cpTables.ReflectChangeParams(dgCustomps.SelectedIndex);

      if (dgParams.SelectedIndex != -1)
      {
        int selIndex = dgParams.SelectedIndex;
        dgParams.SelectedIndex = -1;
        dgParams.SelectedIndex = selIndex;
      }

      if (dgParams.Items.Count == 1) btnDelParam.IsEnabled = false;
      btnOk.IsEnabled = true;
    }



    public CustompTables Show(Window owner, TMCData data, TmcTables tables, int index)
    {
      this.Owner = owner;
      this.Owner.IsEnabled = false;
      btnOk.IsEnabled = false;

      tmcTables = tables;
      tmcData = data;

      cpTables = null;
      cpTables = new CustompTables(tmcData, tmcTables);
      this.DataContext = cpTables;

      if (this.ActualHeight != 0)
      {
        this.Top = owner.Top + (owner.ActualHeight / 2) - (this.ActualHeight / 2);
        this.Left = owner.Left + (owner.ActualWidth / 2) - (this.ActualWidth / 2);
      }

      if (index != -1)
      {
        dgCustomps.SelectedIndex = index;
        dgCustomps.ScrollIntoView(dgCustomps.Items[index]);
      }



      IsActivated = false;
      this.ShowDialog();

      if (cpTables != null && cpTables.Params != null && cpTables.Params.Count != 0) cpTables.Params.Clear();
      dgCustomps.SelectedIndex = -1;
      cmbParam.IsEnabled = false;
      btnAddParam.IsEnabled = false;
      btnDelParam.IsEnabled = false;

      this.Owner.IsEnabled = true;
      this.Owner.Focus();

      if (dialogResult)
      {
        return cpTables;
      }
      else
      {
        return null;
      }
    }

    private void paramListBuild()
    {
      if (cmbParam.Items.Count > 0) cmbParam.Items.Clear();
      paramListData = new SortedSet<uint>();

      paramListData.Add(0x60121B1E);
      paramListData.Add(0x854D87AE);
      paramListData.Add(0xA1314D12);
      paramListData.Add(0xC65C0D8B);
      paramListData.Add(0xD66548AD);
      paramListData.Add(0xE8347F43);
      paramListData.Add(0xEAD201FC);
      paramListData.Add(0xEB53FEEF);

      foreach (var customp in cpTables.Customps)
      {
        foreach (var cp in customp.cp)
        {
          paramListData.Add(cp.Data1);
        }
      }

      foreach (var data in paramListData)
      {
        string type = "Unknown";
        switch (data)
        {
          case 0x60121B1E:
            type = "Wet(Tex)";
            break;
          //case 0xD66548AD:
          //  type = "Wet(Col)";
          //  break;
          case 0xEB53FEEF:
            type = "Skin";
            break;
        }
        cmbParam.Items.Add("0x" + data.ToString("X8") + " : " + type);
      }

      if (cmbParam.Items.Count > 0)
      {
        cmbParam.SelectedIndex = 0;
        cmbParam.IsEnabled = true;
        checkBtnAddParam();
      }
    }

    private void checkBtnAddParam()
    {
      int idx = Array.FindIndex(cpTables.Params.ToArray(), elem => elem.TypeVal == paramListData.ToArray()[cmbParam.SelectedIndex]);
      if (idx == -1)
        btnAddParam.IsEnabled = true;
      else
        btnAddParam.IsEnabled = false;
    }

    public bool checkGettingMateCp(GettingMaterial gettingMat)
    {
      // 既に同じものがあるかチェック（置換の場合は置換先は除く）
      List<int> equalMateCp = new List<int>();
      foreach (var matecp in cpTables.Customps)
      {
        if (!gettingMat.MateCpAdd && matecp.Index == gettingMat.MateCpTarget) continue;
        if (matecp.cp.Count != gettingMat.MateCp.cp.Count) continue;
        for (int i = 0; i < matecp.cp.Count; i++)
        {
          if (
            matecp.cp[i].Data1 != gettingMat.MateCp.cp[i].Data1 ||
            matecp.cp[i].Data2 != gettingMat.MateCp.cp[i].Data2 ||
            matecp.cp[i].Param != gettingMat.MateCp.cp[i].Param
            )
          {
            goto SkipAdd;
          }
        }
        equalMateCp.Add(matecp.Index);

      SkipAdd:;
      }

      // 同じものがあれば追加するか確認
      if (equalMateCp.Count > 0)
      {
        string str = txt["ConfirmReplace"];
        if (gettingMat.MateCpAdd) str = txt["ConfirmAdd"];

        string equalMateCpText = "   MateCp :";
        foreach (var mat in equalMateCp)
        {
          equalMateCpText += " " + mat;
        }
        string result = MessageWindow.Show(this, txt["SameMateCp"] + equalMateCpText + "\r\n" + str, txt["Confirm"], txt["Yes"], txt["No"]);
        if (result == "Cancel")
        {
          return false;
        }
      }
      return true;
    }



    private void Window_Activated(object sender, EventArgs e)
    {
      if (!IsActivated) IsActivated = true;
    }

    private void Window_Closing(object sender, CancelEventArgs e)
    {
      e.Cancel = true;
      IsActivated = false;
      this.Hide();
      if (this.Owner != null) this.Owner.Activate();
    }
  }
}
