using System;
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 GetMaterialWindow : 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 TMCData tmcReferData;
    private static List<TmcTables.ObjectData> selObjData;

    private static List<List<int>> objListData;

    private static byte[] referBn;

    private static string tmcPath = "";

    private bool direct = true;
    private bool IsActivated = false;

    public GetMaterialWindow()
    {
      InitializeComponent();

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

      title.Text = txt["getMatTitle"];
      labelTmcFile.Content = txt["getMatLabelTmcFile"];
      labelGetObj.Content = txt["getMatLabelGetObj"];
      labelMatData.Content = txt["getMatLabelMatData"];
      rbMtrColAdd.Content = txt["Add"];
      rbMtrColReplace.Content = txt["Replace"];
      rbMateCpAdd.Content = txt["Add"];
      rbMateCpReplace.Content = txt["Replace"];
      rbMcaMtrlAdd.Content = txt["Add"];
      rbMcaMtrlReplace.Content = txt["Replace"];
      cbTexParam.Content = txt["getMatTexParam"];
      textAlert.Text = txt["getMatTextAlert"];
      labelInfluenceObj.Content = txt["InfluenceObj"];
      btnOk.Content = txt["OK"];
      btnCancel.Content = txt["Cancel"];
    }

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

    private void Window_DragOver(object sender, DragEventArgs e)
    {
      e.Handled = true;
      if (e.Data.GetDataPresent(DataFormats.FileDrop))
      {
        e.Effects = DragDropEffects.Copy;
      }
      else
      {
        e.Effects = DragDropEffects.None;
      }
    }

    private void Window_DragDrop(object sender, DragEventArgs e)
    {
      string[] filePaths = (string[])e.Data.GetData(DataFormats.FileDrop, false);
      if (Path.GetExtension(filePaths[0]).ToUpper() == ".TMC")
      {
        OpenFile(filePaths[0]);
      }
    }

    private void btnOpen_Click(object sender, RoutedEventArgs e)
    {
      Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
      dlg.Filter = "TMC Files (.TMC)|*.TMC";
      if (tmcPath != "")
      {
        dlg.InitialDirectory = Path.GetDirectoryName(tmcPath);
        dlg.FileName = Path.GetFileName(tmcPath);
      }
      if (dlg.ShowDialog() == true)
      {
        OpenFile(dlg.FileName);
      }
    }

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

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

    private void cmbObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
      ComboBox target = sender as ComboBox;

      if (target.IsMouseCaptured || target.IsKeyboardFocused)
      {
        checkMaterialData();
      }
    }

    private void cbMtrCol_Checked(object sender, RoutedEventArgs e)
    {
      rbMtrColAdd.IsEnabled = true;
      if (selObjData.Count <= 1)
        rbMtrColReplace.IsEnabled = true;
      else
        rbMtrColAdd.IsChecked = true;

      influenceObjListBuild();

      CheckBox cb = sender as CheckBox;
      if (!cb.IsEnabled) return;

      btnOk.IsEnabled = true;
    }

    private void cbMtrCol_Unchecked(object sender, RoutedEventArgs e)
    {
      rbMtrColAdd.IsEnabled = false;
      rbMtrColReplace.IsEnabled = false;

      influenceObjListBuild();

      if (cbMcaMtrl.IsChecked == false && cbMateCp.IsChecked == false && cbTexParam.IsChecked == false) btnOk.IsEnabled = false;
    }

    private void cbMateCp_Checked(object sender, RoutedEventArgs e)
    {
      rbMateCpAdd.IsEnabled = true;
      if (selObjData.Count <= 1)
        rbMateCpReplace.IsEnabled = true;
      else
        rbMateCpAdd.IsChecked = true;

      influenceObjListBuild();

      CheckBox cb = sender as CheckBox;
      if (!cb.IsEnabled) return;

      btnOk.IsEnabled = true;
    }

    private void cbMateCp_Unchecked(object sender, RoutedEventArgs e)
    {
      rbMateCpAdd.IsEnabled = false;
      rbMateCpReplace.IsEnabled = false;

      influenceObjListBuild();

      if (cbMtrCol.IsChecked == false && cbMcaMtrl.IsChecked == false && cbTexParam.IsChecked == false) btnOk.IsEnabled = false;
    }

    private void cbMcaMtrl_Checked(object sender, RoutedEventArgs e)
    {
      rbMcaMtrlAdd.IsEnabled = true;
      if (selObjData.Count <= 1)
        rbMcaMtrlReplace.IsEnabled = true;
      else
        rbMcaMtrlAdd.IsChecked = true;

      influenceObjListBuild();

      CheckBox cb = sender as CheckBox;
      if (!cb.IsEnabled) return;

      btnOk.IsEnabled = true;
    }

    private void cbMcaMtrl_Unchecked(object sender, RoutedEventArgs e)
    {
      rbMcaMtrlAdd.IsEnabled = false;
      rbMcaMtrlReplace.IsEnabled = false;

      influenceObjListBuild();

      if (cbMtrCol.IsChecked == false && cbMateCp.IsChecked == false && cbTexParam.IsChecked == false) btnOk.IsEnabled = false;
    }



    private void rbMtrColAdd_Checked(object sender, RoutedEventArgs e)
    {
      if (!IsInitialized) return;
      influenceObjListBuild();
    }

    private void rbMateCpAdd_Checked(object sender, RoutedEventArgs e)
    {
      if (!IsInitialized) return;
      influenceObjListBuild();
    }

    private void rbMcaMtrlAdd_Checked(object sender, RoutedEventArgs e)
    {
      if (!IsInitialized) return;
      influenceObjListBuild();
    }



    private void rbMtrColReplace_Checked(object sender, RoutedEventArgs e)
    {
      cmbMtrCol.IsEnabled = true;
      influenceObjListBuild();
    }

    private void rbMtrColReplace_Unchecked(object sender, RoutedEventArgs e)
    {
      cmbMtrCol.IsEnabled = false;
    }

    private void rbMateCpReplace_Checked(object sender, RoutedEventArgs e)
    {
      cmbMateCp.IsEnabled = true;
      influenceObjListBuild();
    }

    private void rbMateCpReplace_Unchecked(object sender, RoutedEventArgs e)
    {
      cmbMateCp.IsEnabled = false;
    }

    private void rbMcaMtrlReplace_Checked(object sender, RoutedEventArgs e)
    {
      cmbMcaMtrl.IsEnabled = true;
      influenceObjListBuild();
    }

    private void rbMcaMtrlReplace_Unchecked(object sender, RoutedEventArgs e)
    {
      cmbMcaMtrl.IsEnabled = false;
    }



    private void rbMtrColReplace_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
      RadioButton rb = sender as RadioButton;
      if (rb.IsEnabled && rb.IsChecked == true)
        cmbMtrCol.IsEnabled = true;
      else
        cmbMtrCol.IsEnabled = false;
    }

    private void rbMateCpReplace_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
      RadioButton rb = sender as RadioButton;
      if (rb.IsEnabled && rb.IsChecked == true)
        cmbMateCp.IsEnabled = true;
      else
        cmbMateCp.IsEnabled = false;
    }

    private void rbMcaMtrlReplace_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
      RadioButton rb = sender as RadioButton;
      if (rb.IsEnabled && rb.IsChecked == true)
        cmbMcaMtrl.IsEnabled = true;
      else
        cmbMcaMtrl.IsEnabled = false;
    }



    private void cmbMat_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
      ComboBox target = sender as ComboBox;

      if (target.IsMouseCaptured || target.IsKeyboardFocused) influenceObjListBuild();
    }
    

    private void cbTexParam_Checked(object sender, RoutedEventArgs e)
    {
      influenceObjListBuild();
      btnOk.IsEnabled = true;
    }

    private void cbTexParam_Unchecked(object sender, RoutedEventArgs e)
    {
      influenceObjListBuild();
      if (cbMtrCol.IsChecked == false && cbMcaMtrl.IsChecked == false && rbMateCpAdd.IsChecked == false)
        btnOk.IsEnabled = false;
    }



    public void Init(TMCData tmcdata)
    {
      tmcData = tmcdata;
      matListBuild();
    }

    public GettingMaterial Show(Window owner, TmcTables tables, List<TmcTables.ObjectData> objs, string type, int index)
    {
      this.Owner = owner;
      Owner.IsEnabled = false;

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

      tmcTables = tables;
      selObjData = objs;
      if (selObjData == null)
      {
        textAlert.Visibility = Visibility.Collapsed;
      }
      else
      {
        textAlert.Visibility = Visibility.Visible;
        if (selObjData.Count > 0)
        {
          cmbMtrCol.SelectedValue = selObjData[0].MtrCol;
          if (selObjData[0].Matecp != null && selObjData[0].Matecp != tables.Matecps.Count - 1)
            cmbMateCp.SelectedValue = selObjData[0].Matecp;
          if (selObjData[0].Mcamtrl != null && selObjData[0].Mcamtrl != -1)
            cmbMcaMtrl.SelectedValue = selObjData[0].Mcamtrl;
        }
      }

      if (type == "MtrCol" || type == "matecp" || type == "MCAMTRL")
      {
        direct = false;
        gridMtrCol.Visibility = Visibility.Collapsed;
        gridMateCp.Visibility = Visibility.Collapsed;
        gridMCAMTRL.Visibility = Visibility.Collapsed;
        cbTexParam.Visibility = Visibility.Collapsed;
        textAlert.Visibility = Visibility.Collapsed;
      }
      else
      {
        direct = true;
        gridMtrCol.Visibility = Visibility.Visible;
        gridMateCp.Visibility = Visibility.Visible;
        gridMCAMTRL.Visibility = Visibility.Visible;
        cbTexParam.Visibility = Visibility.Visible;
        textAlert.Visibility = Visibility.Visible;
      }

      if (type == "MtrCol")
      {
        cbMtrCol.IsChecked = true;
        gridMtrCol.Visibility = Visibility.Visible;
        if (index != -1) cmbMtrCol.SelectedValue = index;
      }
      else
        cbMtrCol.IsChecked = false;

      if (type == "matecp")
      {
        cbMateCp.IsChecked = true;
        gridMateCp.Visibility = Visibility.Visible;
        if (index != -1) cmbMateCp.SelectedValue = index;
      }
      else
        cbMateCp.IsChecked = false;

      if (type == "MCAMTRL")
      {
        cbMcaMtrl.IsChecked = true;
        gridMCAMTRL.Visibility = Visibility.Visible;
        if (index != -1) cmbMcaMtrl.SelectedValue = index;
      }
      else
        cbMcaMtrl.IsChecked = false;

      cbTexParam.IsChecked = false;

      IsActivated = false;
      this.ShowDialog();

      if (direct)
      {
        Owner.IsEnabled = true;
        Owner.Focus();
      }

      if (dialogResult)
      {
        GettingMaterial gettingMat = new GettingMaterial();

        int grpID = grpID = objListData[cmbObject.SelectedIndex][0];
        int objID = objID = objListData[cmbObject.SelectedIndex][1];

        // MtrCol
        if (cbMtrCol.IsChecked == true)
        {
          MtrColorGroup col = tmcReferData.ColGrp[tmcReferData.ObjGrp[grpID].Obj[objID].MtrColor];

          int target = -1;
          if (rbMtrColReplace.IsChecked == true) target = (int)cmbMtrCol.SelectedValue;

          gettingMat.SetColData(col.Start - col.Offset, col.Offset, referBn, target);
        }

        // matecp
        if (cbMateCp.IsEnabled && cbMateCp.IsChecked == true)
        {
          Customp cp = tmcReferData.MateCp[tmcReferData.Itable[grpID].Indices[objID]];

          int target = -1;
          if (rbMateCpReplace.IsChecked == true) target = (int)cmbMateCp.SelectedValue;

          gettingMat.SetMateCpData(cp.Start - cp.Offset, cp.Offset, referBn, target);
        }

        // MCAMTRL
        if (cbMcaMtrl.IsEnabled && cbMcaMtrl.IsChecked == true)
        {
          Material mat = tmcReferData.Mat[tmcReferData.McaIdx[grpID].MatID[objID]];

          int target = -1;
          if (rbMcaMtrlReplace.IsChecked == true) target = (int)cmbMcaMtrl.SelectedValue;

          gettingMat.SetMatData(mat.Start - mat.Offset, mat.Offset, referBn, target);
        }

        // TexParam
        if (cbTexParam.IsChecked == true)
        {
          gettingMat.SetObjTexData(tmcReferData.ObjGrp[grpID].Obj[objID], referBn);
        }

        return gettingMat;
      }
      else
      {
        return null;
      }
    }

    private void objectListBuild()
    {
      if (cmbObject.Items.Count > 0) cmbObject.Items.Clear();
      objListData = new List<List<Int32>>();

      int grpCount = 0;
      foreach (var grp in tmcReferData.ObjGrp)
      {
        int objCount = 0;
        foreach (var obj in grp.Obj)
        {
          cmbObject.Items.Add(grp.Name + "_" + obj.ID.ToString("x"));
          List<Int32> data = new List<Int32>();
          data.Add(grpCount);
          data.Add(objCount);
          objListData.Add(data);

          objCount++;
        }
        grpCount++;
      }

      if (cmbObject.Items.Count > 0)
      {
        cmbObject.SelectedIndex = 0;
        checkMaterialData();
        cmbObject.IsEnabled = true;
      }
    }

    private void matListBuild()
    {
      if (cmbMtrCol.Items.Count > 0) cmbMtrCol.Items.Clear();
      foreach (var col in tmcData.ColGrp) cmbMtrCol.Items.Add(col.ID);
      if (cmbMtrCol.Items.Count > 0) cmbMtrCol.SelectedIndex = 0;

      if (cmbMcaMtrl.Items.Count > 0) cmbMcaMtrl.Items.Clear();
      if (tmcData.Mat != null) foreach (var mat in tmcData.Mat) cmbMcaMtrl.Items.Add(mat.ID);
      if (cmbMcaMtrl.Items.Count > 0) cmbMcaMtrl.SelectedIndex = 0;

      if (cmbMateCp.Items.Count > 0) cmbMateCp.Items.Clear();
      if (tmcData.MateCp != null) foreach (var matecp in tmcData.MateCp) cmbMateCp.Items.Add(matecp.Index);
      if (cmbMateCp.Items.Count > 0) cmbMateCp.SelectedIndex = 0;
    }

    private void influenceObjListBuild()
    {
      listInfluenceObj.Text = "";
      listInfluenceObj.IsEnabled = false;
      if (cbMtrCol.IsChecked == false && cbMcaMtrl.IsChecked == false && cbMateCp.IsChecked == false && cbTexParam.IsChecked == false)
      {
        return;
      }
      else if (
        (cbMtrCol.IsChecked == false || rbMtrColAdd.IsChecked == true) &&
        (cbMcaMtrl.IsChecked == false || rbMcaMtrlAdd.IsChecked == true) &&
        (cbMateCp.IsChecked == false || rbMateCpAdd.IsChecked == true)
      )
      {
        if (selObjData != null)
        {
          foreach (var obj in selObjData)
          {
            if (listInfluenceObj.Text != "") listInfluenceObj.Text += "\r\n";
            listInfluenceObj.Text += obj.Name;
          }
          listInfluenceObj.IsEnabled = true;
        }
      }
      else
      {
        foreach (var obj in tmcTables.ObjData)
        {
          if (obj.Grp == -1) continue;

          if (
            (cmbMtrCol.IsEnabled && obj.MtrCol == (int)cmbMtrCol.SelectedValue) ||
            (cmbMcaMtrl.IsEnabled && obj.Mcamtrl == (int)cmbMcaMtrl.SelectedValue) ||
            (cbMateCp.IsEnabled && obj.Matecp == (int)cmbMateCp.SelectedValue) ||
            (
              (
                (rbMtrColAdd.IsEnabled && rbMtrColAdd.IsChecked == true) ||
                (rbMcaMtrlAdd.IsEnabled && rbMcaMtrlAdd.IsChecked == true) ||
                (rbMateCpAdd.IsEnabled && rbMateCpAdd.IsChecked == true) ||
                (cbTexParam.IsChecked == true)
              ) && Array.FindIndex(selObjData.ToArray(), elem => elem.Grp == obj.Grp && elem.ID == obj.ID) != -1
            )
          )
          {
            if (listInfluenceObj.Text != "") listInfluenceObj.Text += "\r\n";
            listInfluenceObj.Text += obj.Name;
          }
        }
        if (listInfluenceObj.Text != "") listInfluenceObj.IsEnabled = true;
      }
    }

    private void checkMaterialData()
    {
      if (cmbObject.Items.Count == 0) return;

      var grp = tmcReferData.ObjGrp[objListData[cmbObject.SelectedIndex][0]];
      var obj = tmcReferData.ObjGrp[objListData[cmbObject.SelectedIndex][0]].Obj[objListData[cmbObject.SelectedIndex][1]];

      gridMtrCol.IsEnabled = true;
      cbTexParam.IsEnabled = true;

      if (tmcData.Mat != null && tmcReferData.McaIdx != null && tmcReferData.McaIdx[grp.ID].MatID[obj.ID] != -1)
        gridMCAMTRL.IsEnabled = true;
      else
        gridMCAMTRL.IsEnabled = false;

      if (tmcData.MateCp != null && tmcReferData.MateCp != null && tmcReferData.Itable[grp.ID].Indices[obj.ID] != tmcReferData.MateCp.Count)
        gridMateCp.IsEnabled = true;
      else
        gridMateCp.IsEnabled = false;

      textTexCount.Text = obj.TexCount.ToString();
    }



    private void OpenFile(string filePath)
    {
      try
      {
        cmbObject.IsEnabled = false;
        gridMtrCol.IsEnabled = false;
        rbMtrColAdd.IsEnabled = false;
        rbMtrColReplace.IsEnabled = false;
        gridMCAMTRL.IsEnabled = false;
        rbMcaMtrlAdd.IsEnabled = false;
        rbMcaMtrlReplace.IsEnabled = false;
        cbTexParam.IsEnabled = false;

        referBn = System.IO.File.ReadAllBytes(filePath);
        char[] charsToTrim = { '\0' };
        string Name = Encoding.ASCII.GetString(referBn, 0, 8).TrimEnd(charsToTrim);
        if (Name != "TMC")
        {
          MessageWindow.Show(this, txt["NotTMC"] + " / " + this.Name, txt["Error"]);
        }
        uint Flg1 = BitConverter.ToUInt32(referBn, 0x08);
        if (Flg1 != 16842752)
        {
          MessageWindow.Show(this, txt["UnsupportedTMC"], txt["Error"]);
        }

        tmcReferData = new TMCData(referBn);
        tmcReferData.ParseObjBaseData(referBn);
        tmcReferData.ParseMtrColor(referBn);
        if (tmcReferData.H.Offsets[12] != 0) tmcReferData.ParseMCAPack(referBn);

        if (tmcReferData != null)
        {
          objectListBuild();

          if (cbMtrCol.IsChecked == true)
          {
            rbMtrColAdd.IsEnabled = true;
            if (selObjData.Count <= 1) rbMtrColReplace.IsEnabled = true;
            if (gridMtrCol.Visibility == Visibility.Visible) btnOk.IsEnabled = true;
          }
          if (cbMateCp.IsChecked == true)
          {
            rbMateCpAdd.IsEnabled = true;
            if (selObjData.Count <= 1) rbMateCpReplace.IsEnabled = true;
            if (gridMateCp.Visibility == Visibility.Visible) btnOk.IsEnabled = true;
          }
          if (cbMcaMtrl.IsChecked == true)
          {
            rbMcaMtrlAdd.IsEnabled = true;
            if (selObjData.Count <= 1) rbMcaMtrlReplace.IsEnabled = true;
            if (gridMCAMTRL.Visibility == Visibility.Visible) btnOk.IsEnabled = true;
          }

          textFilePath.Path = filePath;
        }
      }
      catch (Exception e)
      {
        MessageWindow.Show(this, e.Message + "\r\n\r\n" + e.StackTrace, txt["Error"]);
      }
    }





    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();
    }
  }
}
