using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace JtkManagerClient {
    public partial class PcMapForm : Form {
        public string ResultPcMapJson = null;

        public PcMapForm(PcListViewItem[] items) {
            InitializeComponent();

            foreach (var item in items) {
                pcListView.Items.Add(new PcListViewItem(pcId: item.PcId) { Mode = PcListViewItem.PcListViewItemPanelMode.ShowId, Number = item.Number, Row = item.Row, Column = item.Column });
            }
            pcListView.Redraw();
        }

        #region Not Placed PC List View Drags
        private void notPlacedPcListView_ItemDrag(object sender, ItemDragEventArgs e) {
            if (notPlacedPcListView.SelectedItems.Count == 1) {
                notPlacedPcListView.DoDragDrop(notPlacedPcListView.SelectedItems, DragDropEffects.Move);
            }
        }

        private void notPlacedPcListView_DragEnter(object sender, DragEventArgs e) {
            foreach (var format in e.Data.GetFormats()) {
                if (format.StartsWith("System.Collections.Generic.HashSet")) {
                    e.Effect = DragDropEffects.Move;
                }
            }
        }

        private void notPlacedPcListView_DragDrop(object sender, DragEventArgs e) {
            foreach (var format in e.Data.GetFormats()) {
                if (format.StartsWith("System.Collections.Generic.HashSet")) {
                    notPlacedPcListView.SelectedItems.Clear();
                    foreach (var item in pcListView.SelectedItems) {
                        item.Owner = null;
                        item.Selected = false;
                        notPlacedPcListView.Items.Add(new ListViewItem($"{item.Number:000} ({item.PcId})") { Tag = item, Selected = true });
                        pcListView.Items.Remove(item);
                    }
                    pcListView.Redraw();
                }
            }
        }
        #endregion

        #region PC List View Drags
        private void pcListView_ItemDrag(object sender, ItemDragEventArgs e) {
            pcListView.DoDragDrop(pcListView.SelectedItems, DragDropEffects.Move);
        }

        private void pcListView_DragEnter(object sender, DragEventArgs e) {
            foreach (var format in e.Data.GetFormats()) {
                if (format == "System.Windows.Forms.ListView+SelectedListViewItemCollection" || format.StartsWith("System.Collections.Generic.HashSet") && pcListView.SelectedItems.Count == 1) {
                    e.Effect = DragDropEffects.Move;
                }
            }
        }

        private void pcListView_DragDrop(object sender, DragEventArgs e) {
            foreach (var format in e.Data.GetFormats()) {
                if (format == "System.Windows.Forms.ListView+SelectedListViewItemCollection") {
                    foreach (var item in pcListView.SelectedItems) {
                        item.Selected = false;
                    }
                    foreach (ListViewItem item in notPlacedPcListView.SelectedItems) {
                        var pos = pcListView.PointToClient(MousePosition);
                        (var row, var col) = pcListView.GetRowColumnAt(pos.X, pos.Y);
                        var pcMapItem = item.Tag as PcListViewItem;
                        pcMapItem.Row = row;
                        pcMapItem.Column = col;
                        pcMapItem.Selected = true;
                        pcListView.Items.Add(pcMapItem);
                        
                        notPlacedPcListView.Items.Remove(item);
                    }
                    pcListView.Redraw();
                } else if (format.StartsWith("System.Collections.Generic.HashSet")) {
                    var pos = pcListView.PointToClient(MousePosition);
                    (var row, var col) = pcListView.GetRowColumnAt(pos.X, pos.Y);
                    var pcMapItem = pcListView.SelectedItems.First();
                    pcMapItem.Row = row;
                    pcMapItem.Column = col;
                    pcListView.Redraw();
                }
            }
            UpdateDetails(true);
        }
        #endregion

        private void acceptButton_Click(object sender, EventArgs e) {
            DialogResult = DialogResult.OK;
            var result = new JObject();
            foreach (var item in pcListView.Items) {
                result[item.PcId] = JToken.FromObject(new { num = item.Number, row = item.Row, col = item.Column });
            }
            ResultPcMapJson = result.ToString();

            Close();
        }

        private void addButton_Click(object sender, EventArgs e) {
            var form = new PcMapAddForm();
            if (form.ShowDialog() == DialogResult.OK) {
                var result = form.Result;
                var passedCount = 0;
                foreach (var tuple in result) {
                    var pcId = tuple.id;
                    var pcNumber = tuple.number;
                    var listViewItem = new ListViewItem($"{pcNumber:000} ({pcId})") { Tag = new PcListViewItem(pcId) { Number = pcNumber, Mode = PcListViewItem.PcListViewItemPanelMode.ShowId } };
                    
                    // ★★★★★ PC ID와 Number 중복체크하고 넣어야지! ★★★★★
                    if (true) {
                        notPlacedPcListView.Items.Add(listViewItem);
                    } else {
                        passedCount++;
                    }
                }
            }
        }

        private void removeButton_Click(object sender, EventArgs e) {
            if (MessageBox.Show("삭제하시겠습니까?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No) {
                return;
            }
            foreach (ListViewItem item in notPlacedPcListView.SelectedItems) {
                notPlacedPcListView.Items.Remove(item);
            }
        }

        private void notPlacedPcListView_SelectedIndexChanged(object sender, EventArgs e) {
            UpdateDetails(false);
        }

        private void pcListView_SelectedItemChanged(object sender, EventArgs e) {
            UpdateDetails(true);
        }

        private void UpdateDetails(bool right = false) {
            if (right) {
                if (pcListView.SelectedItems.Count == 1) {
                    var item = pcListView.SelectedItems.First();
                    idTextBox.Text = item.PcId;
                    numberTextBox.Text = item.Number.ToString("000");
                } else {
                    idTextBox.Text = numberTextBox.Text = "-";
                }
            } else {
                removeButton.Enabled = notPlacedPcListView.SelectedItems.Count > 0;
                if (notPlacedPcListView.SelectedItems.Count == 1) {
                    var item = notPlacedPcListView.SelectedItems[0].Tag as PcListViewItem;
                    idTextBox.Text = item.PcId;
                    numberTextBox.Text = item.Number.ToString("000");
                } else {
                    idTextBox.Text = numberTextBox.Text = "-";
                }
            }
        }

        private void numberTextBox_KeyDown(object sender, KeyEventArgs e) {
            if (e.KeyCode == Keys.Enter) {
                ApplyNumberTextBox();
            }
        }

        private void numberTextBox_Enter(object sender, EventArgs e) {
            AcceptButton = null;
        }

        private void numberTextBox_Leave(object sender, EventArgs e) {
            AcceptButton = acceptButton;
        }

        private void ApplyNumberTextBox() {
            var pcId = idTextBox.Text;
            if (int.TryParse(numberTextBox.Text, out var number) && 1 <= number && number <= 999) {
                // 원래번호와 비교
                var oldNumber = 0;
                var leftNumbers = 
                    from ListViewItem item in notPlacedPcListView.Items
                    where (item.Tag as PcListViewItem).PcId == pcId
                    select (item.Tag as PcListViewItem).Number;
                var rightNumbers =
                    from item in pcListView.Items
                    where item.PcId == pcId
                    select item.Number;
                foreach (var n in leftNumbers) {
                    oldNumber = n;
                }
                foreach (var n in rightNumbers) {
                    oldNumber = n;
                }
                if (oldNumber == number) {
                    numberTextBox.Text = number.ToString("000");
                    return;
                }

                // 중복검사
                var overlapped = false;
                foreach (ListViewItem i in notPlacedPcListView.Items) {
                    var item = i.Tag as PcListViewItem;
                    if (item.Number == number) {
                        overlapped = true;
                    }
                    if (item.PcId == pcId) {
                        oldNumber = item.Number;
                    }
                }
                if (overlapped == false) {
                    foreach (var item in pcListView.Items) {
                        if (item.Number == number) {
                            overlapped = true;
                            break;
                        }
                        if (item.PcId == pcId) {
                            oldNumber = item.Number;
                        }
                    }
                }
                if (overlapped) {
                    MessageBox.Show("번호가 중복됩니다.", "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                // 적용하기
                var done = false;
                foreach (ListViewItem i in notPlacedPcListView.Items) {
                    var item = i.Tag as PcListViewItem;
                    if (item.PcId == pcId) {
                        item.Number = number;
                        i.Text = $"{item.Number:000} ({item.PcId})";
                        done = true;
                        break;
                    }
                }
                if (done == false) {
                    foreach (var item in pcListView.Items) {
                        if (item.PcId == pcId) {
                            item.Number = number;
                            break;
                        }
                    }
                }
                numberTextBox.Text = number.ToString("000");
                pcListView.Redraw();
            } else {
                MessageBox.Show("1부터 999 사이의 유효한 값을 입력하세요.", "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                // 원래대로 돌리기
                var done = false;
                foreach (ListViewItem i in notPlacedPcListView.Items) {
                    var item = i.Tag as PcListViewItem;
                    if (item.PcId == pcId) {
                        numberTextBox.Text = item.Number.ToString("000");
                        done = true;
                        break;
                    }
                }
                if (done == false) {
                    foreach (var item in pcListView.Items) {
                        if (item.PcId == pcId) {
                            numberTextBox.Text = item.Number.ToString("000");
                            break;
                        }

                    }
                }
            }
        }
    }
}
