using System;
using System.IO;
using System.IO.Compression;
using System.Windows.Forms;
using System.Drawing;
using System.Linq;
using System.Collections.Generic;

public class M : Form {
    string cfg = AppDomain.CurrentDomain.BaseDirectory + "config.txt";
    Button b1 = new Button() { Text = "Ϳ  ", Left = 30, Top = 20, Width = 210, Height = 60, Font = new Font(" ", 10, FontStyle.Bold), BackColor = Color.SkyBlue };
    Button b2 = new Button() { Text = "  ", Left = 260, Top = 20, Width = 210, Height = 60, Font = new Font(" ", 10, FontStyle.Bold), BackColor = Color.Salmon };
    Label l1 = new Label() { Text = "Ϳ ", Left = 30, Top = 100, Font = new Font(" ", 9, FontStyle.Bold), AutoSize = true };
    TextBox t1 = new TextBox() { Left = 30, Top = 125, Width = 350, Height = 30, Text = @"C:\Program Files (x86)\World of Warcraft\_retail_", Font = new Font(" ", 10) };
    Button s1 = new Button() { Text = "", Left = 390, Top = 124, Width = 80, Height = 25, Font = new Font(" ", 9) };
    Label l2 = new Label() { Text = " ", Left = 30, Top = 175, Font = new Font(" ", 9, FontStyle.Bold), AutoSize = true };
    TextBox t2 = new TextBox() { Left = 30, Top = 200, Width = 350, Height = 30, Font = new Font(" ", 10) };
    Button s2 = new Button() { Text = "", Left = 390, Top = 199, Width = 80, Height = 25, Font = new Font(" ", 9) };
    Label l3 = new Label() { Text = "ֱ    (ִ 5 ǥ)", Left = 30, Top = 245, Font = new Font(" ", 9, FontStyle.Bold), AutoSize = true };
    ListBox lb = new ListBox() { Left = 30, Top = 270, Width = 440, Height = 90, Font = new Font(" ", 10) };
    Label l4 = new Label() { Text = " ", Left = 30, Top = 380, Font = new Font(" ", 9, FontStyle.Bold), AutoSize = true };
    Label statusLabel = new Label() { Text = "(   )", Left = 100, Top = 380, Width = 370, ForeColor = Color.DarkSlateGray, Font = new Font(" ", 9, FontStyle.Regular) };
    ProgressBar pb = new ProgressBar() { Left = 30, Top = 405, Width = 440, Height = 20 };
    Label info1 = new Label() { Text = " : üũ  Ͽ մϴ.", Left = 30, Top = 440, Width = 440, ForeColor = Color.Blue, Font = new Font(" ", 9) };
    Label info2 = new Label() { Text = " : üũ      մϴ.", Left = 30, Top = 460, Width = 440, ForeColor = Color.Red, Font = new Font(" ", 9) };
    CheckBox c1 = new CheckBox() { Text = "Fonts", Left = 30, Top = 490, Checked = false, Font = new Font(" ", 9) };
    CheckBox c2 = new CheckBox() { Text = "Interface", Left = 160, Top = 490, Checked = true, Font = new Font(" ", 9) };
    CheckBox c3 = new CheckBox() { Text = "WTF", Left = 290, Top = 490, Checked = true, Font = new Font(" ", 9) };

    public M() {
        this.Text = "Ϳ / Ŵ -  V1.2"; 
        this.Size = new Size(516, 580);
        this.StartPosition = FormStartPosition.CenterScreen;
        string defaultPath = Directory.Exists("D:\\") ? "D:\\WoW_Backup" : "C:\\WoW_Backup";
        t2.Text = defaultPath;
        try { this.Icon = new Icon("icon.ico"); } catch { }
        this.Controls.AddRange(new Control[] { b1, b2, l1, l2, l3, l4, statusLabel, t1, t2, s1, s2, lb, pb, info1, info2, c1, c2, c3 });
        LoadCfg();
        s1.Click += delegate { SelectFolder(t1); SaveCfg(); };
        s2.Click += delegate { SelectFolder(t2); SaveCfg(); UpdateList(); };
        b1.Click += delegate { Run(true); }; b2.Click += delegate { Run(false); };
        UpdateList();
    }
    void SaveCfg() { try { File.WriteAllLines(cfg, new string[] { t1.Text, t2.Text }); } catch { } }
    void LoadCfg() { try { if (File.Exists(cfg)) { var l = File.ReadAllLines(cfg); t1.Text = l[0]; if(l.Length > 1) t2.Text = l[1]; } } catch { } }
    void SelectFolder(TextBox tb) {
        using (var f = new OpenFileDialog()) {
            f.Title = " ϼ."; f.ValidateNames = false; f.CheckFileExists = false; f.CheckPathExists = true; f.FileName = " ";
            if (f.ShowDialog() == DialogResult.OK) tb.Text = Path.GetDirectoryName(f.FileName);
        }
    }
    void UpdateList() { lb.Items.Clear(); if (Directory.Exists(t2.Text)) foreach (var f in new DirectoryInfo(t2.Text).GetFiles("*.zip").OrderByDescending(x => x.CreationTime).Take(5)) lb.Items.Add(f.Name); }
    void Run(bool b) {
        string[] targets = { "WTF", "Interface", "Fonts" };
        bool[] checks = { c3.Checked, c2.Checked, c1.Checked };
        pb.Value = 0;
        try {
            if (b) {
                if (!Directory.Exists(t2.Text)) Directory.CreateDirectory(t2.Text);
                var selected = targets.Where((t, i) => checks[i]).ToList();
                if (selected.Count == 0) { MessageBox.Show("  ϼ."); return; }
                if (MessageBox.Show(" Ͻðڽϱ?\n\n[ ]: " + string.Join(", ", selected), " Ȯ", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return;
                string zName = "WoW_" + DateTime.Now.ToString("yyyyMMdd_HHmm") + ".zip";
                string zPath = Path.Combine(t2.Text, zName);
                using (ZipArchive a = ZipFile.Open(zPath, ZipArchiveMode.Create)) {
                    int total = 0;
                    foreach (int i in Enumerable.Range(0, 3).Where(x => checks[x])) 
                        total += Directory.Exists(Path.Combine(t1.Text, targets[i])) ? Directory.GetFiles(Path.Combine(t1.Text, targets[i]), "*", SearchOption.AllDirectories).Length : 0;
                    int cur = 0;
                    for (int i = 0; i < 3; i++) {
                        if (checks[i]) {
                            statusLabel.Text = "(   : " + targets[i] + " )";
                            string p = Path.Combine(t1.Text, targets[i]);
                            foreach (string f in Directory.GetFiles(p, "*", SearchOption.AllDirectories)) {
                                a.CreateEntryFromFile(f, targets[i] + f.Substring(p.Length));
                                cur++; pb.Value = (total > 0) ? (cur * 100 / total) : 100;
                                Application.DoEvents();
                            }
                        }
                    }
                }
                UpdateList();
                MessageBox.Show("  ϷǾϴ.");
            } else {
                using (OpenFileDialog f = new OpenFileDialog()) {
                    f.InitialDirectory = t2.Text; f.Filter = "Zip files (*.zip)|*.zip";
                    var latest = new DirectoryInfo(t2.Text).GetFiles("*.zip").OrderByDescending(x => x.CreationTime).FirstOrDefault();
                    if (latest != null) f.FileName = latest.FullName;
                    if (f.ShowDialog() == DialogResult.OK) {
                        var foldersInZip = new List<string>();
                        using (ZipArchive archive = ZipFile.OpenRead(f.FileName)) {
                            foreach (var entry in archive.Entries) {
                                string root = entry.FullName.Split('/')[0].Split('\\')[0];
                                if (!foldersInZip.Contains(root)) foldersInZip.Add(root);
                            }
                        }
                        var selectedFolders = new List<string>();
                        for(int i=0; i<targets.Length; i++) { if(checks[i]) selectedFolders.Add(targets[i]); }
                        bool isMatch = foldersInZip.OrderBy(x => x).SequenceEqual(selectedFolders.OrderBy(x => x));
                        string warning = isMatch ? "" : "\n\n[]   ٸϴ. Ȯ  ϼ!";
                        string msg = "Ͻðڽϱ?\n\n: " + Path.GetFileName(f.FileName) + 
                                     "\n\n[ ]: " + string.Join(", ", foldersInZip) +
                                     "\n[ ]: " + (selectedFolders.Count > 0 ? string.Join(", ", selectedFolders) : "") + warning;
                        if (MessageBox.Show(msg, " Ȯ", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes) {
                            var entriesToExtract = new List<ZipArchiveEntry>();
                            var foldersInZipSet = new HashSet<string>(foldersInZip);
                            using (ZipArchive archive = ZipFile.OpenRead(f.FileName)) {
                                foreach (var entry in archive.Entries) {
                                    string folder = entry.FullName.Split('/')[0].Split('\\')[0];
                                    if (checks.Any(c => c) && checks[Array.IndexOf(targets, folder)]) entriesToExtract.Add(entry);
                                }
                                int total = entriesToExtract.Count;
                                foreach (var target in targets.Where((t, i) => checks[i] && foldersInZipSet.Contains(t) && Directory.Exists(Path.Combine(t1.Text, t)))) {
                                    statusLabel.Text = "(    : " + target + " )";
                                    Application.DoEvents();
                                    Directory.Delete(Path.Combine(t1.Text, target), true);
                                }
                                for (int i = 0; i < total; i++) {
                                    var entry = entriesToExtract[i];
                                    string folderName = entry.FullName.Split('/')[0].Split('\\')[0];
                                    statusLabel.Text = "(   : " + folderName + "   ... )";
                                    string destPath = Path.Combine(t1.Text, entry.FullName);
                                    Directory.CreateDirectory(Path.GetDirectoryName(destPath));
                                    if (!string.IsNullOrEmpty(entry.Name)) entry.ExtractToFile(destPath, true);
                                    pb.Value = (i + 1) * 100 / total;
                                    Application.DoEvents();
                                }
                            }
                            MessageBox.Show("    ϷǾϴ.");
                        }
                    }
                }
            }
        } catch (Exception ex) { MessageBox.Show(": " + ex.Message); }
        pb.Value = 0; statusLabel.Text = "( ۾ Ϸ )";
    }
    [STAThread] static void Main() { Application.Run(new M()); }
}