// This file is part of GNOME Boxes. License: LGPLv2+

// Automated installer media for Windows XP, 2000 and 2003
private class Boxes.WinXPInstaller: WindowsInstaller {
    private const uint[] allowed_dash_positions = { 5, 11, 17, 23 };

    private static Regex key_regex;
    private static Regex admin_pass_regex;

    private Gtk.Entry key_entry;

    private ulong key_inserted_id; // ID of key_entry.insert_text signal handler

    static construct {
        try {
            key_regex = new Regex ("BOXES_PRODUCT_KEY");
            admin_pass_regex = new Regex ("BOXES_XP_ADMIN_PASSWORD");
        } catch (RegexError error) {
            // This just can't fail
            assert_not_reached ();
        }
    }

    public WinXPInstaller.copy (InstallerMedia media) throws GLib.Error {
        var unattended_source = get_unattended (media.os.short_id + ".sif");
        var avatar_format = new AvatarFormat ("bmp", ".bmp", false, 48, 48);
        base.copy (media, unattended_source, "Winnt.sif", avatar_format);

        var name = media.os.short_id + ".cmd";
        unattended_source = get_unattended (name);
        add_unattended_text_file (unattended_source, name);

        name = media.os.short_id + ".reg";
        unattended_source = get_unattended (name);
        add_unattended_text_file (unattended_source, name);

        newline_type = DataStreamNewlineType.CR_LF;
    }

    protected override void setup_ui () {
        base.setup_ui ();

        setup_table.resize (setup_table.n_rows + 1, setup_table.n_columns);

        var hbox = new Gtk.HBox (false, 10);
        hbox.margin_top = 12;

        // Microsoft Windows product key
        var label = new Gtk.Label (_("Product Key"));
        label.halign = Gtk.Align.START;
        hbox.pack_start (label, true, true, 0);

        var notebook = new Gtk.Notebook ();
        notebook.show_tabs = false;
        notebook.show_border = false;
        var button = new Gtk.Button.with_mnemonic (_("_Add Product Key"));
        notebook.append_page (button);
        key_entry = new Gtk.Entry ();
        key_entry.width_chars = 29;
        key_entry.max_length = 29;
        key_entry.get_style_context ().add_class ("boxes-product-key-entry");
        notebook.append_page (key_entry);

        button.clicked.connect (() => {
            notebook.next_page ();
            key_entry.is_focus = true;
        });

        hbox.pack_start (notebook, true, true, 0);
        setup_table.attach_defaults (hbox, 0, setup_table.n_columns, setup_table.n_rows - 1, setup_table.n_rows);

        express_toggle.bind_property ("active", hbox, "sensitive", 0);

        key_inserted_id = key_entry.insert_text.connect (on_key_text_inserted);
    }

    protected override string fill_unattended_data (string data, string hostname) throws RegexError {
        var str = base.fill_unattended_data (data, hostname);
        var admin_pass = (password != "") ? password : "*";
        str = admin_pass_regex.replace (str, str.length, 0, admin_pass);

        return key_regex.replace (str, str.length, 0, key_entry.text);
    }

    private void on_key_text_inserted (string text, int text_length, ref int position) {
        var result = "";

        uint i = 0;
        foreach (var character  in ((char[]) text.data)) {
            var char_position = i + position;

            if (character != '-') {
                if (!character.isalnum ())
                    continue;

                if (char_position in allowed_dash_positions) {
                    // Insert dash in the right place for our dear user
                    result += "-";
                    i++;
                }
            } else if (!(char_position in allowed_dash_positions))
                continue;

            result += character.to_string ();
            i++;
        }

        if (result != "") {
            SignalHandler.block (key_entry, key_inserted_id);
            key_entry.insert_text (result.up (), result.length, ref position);
            SignalHandler.unblock (key_entry, key_inserted_id);
        }

        Signal.stop_emission_by_name (key_entry, "insert-text");
    }
}
