/*

    Copyright (C) 2020 willipink.eu
    Author Moritz Münch moritzmuench@mailbox.org

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>. */


import { Cookie } from './modules/cookie.mjs';
import { Modal, detach } from './modules/modal.mjs';

let settings = {
    found:        true,
    found_by:     '',
    found_on:     '',
    circulation:  0,
    buy_only:     false,
    checked:      false,
    ec:           false,
    exists:       true }


//
// Functions
//

/* return escaped html */
function escape_html (string) {
    let entity_map = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#39;',
        '/': '&#x2F;',
        '`': '&#x60;',
        '=': '&#x3D;' };
    return String(string).replace(/[&<>"'`=\/]/g, function (s) {
        return entity_map[s]; });
}

/* return a datetime YYYY.MM.DD */
function get_datetime() {
    let datetime = new Date();
    return ('0' +  datetime.getDate()).slice(-2)       + '.' +
           ('0' + (datetime.getMonth() + 1)).slice(-2) + '.' +
                   datetime.getFullYear();
}


// manage user login
function render_login(name, color) {
    new Cookie('coinc-name', name)
    render_login_color(color);

    let option = $('nav.navbar option[value=' + name + ']');
    if (option.length == 0) {
        $('nav.navbar select').append($('<option>', {
            value: name, color: color, html: name
        }));
    }

    $('nav.navbar option[value=' + name + ']').attr('selected', 'selected');
}


// manage login colors
function render_login_color(color) {
    new Cookie('coinc-color', color);

    if ($('nav.navbar').css('display') == 'block') {
        $('nav.navbar').prop('style', 'background-color:' + color + ' !important; display: block;');
    } else {
        $('nav.navbar').attr('style', 'background-color:' + color + ' !important;');
    }
}


// show/update #found_by and #found_on
function render_found() {
    let checked = $('#found').prop('checked');
    if (checked === true) {
        $('#found_by option[selected=selected]').html(settings['found_by']);
        let found_on = ''
        if (settings['found_on']) {
            found_on = settings['found_on'];
        } else {
            found_on = get_datetime();
        }
        $('#found_on').val(found_on);
        $('#checked').prop('checked', settings['checked']);
        $('#ec').prop('checked', settings['ec']);

    } else {
        save_settings();
        $('#found_by option[selected=selected]').html('');
        $('#found_on').val('');
        $('#checked, #ec').each(function() {
            $(this).prop('checked', false); });
    }

    $('#found_by, #found_on, #checked, #ec').each(function() {
        if (checked === true) {
            $(this).prop('disabled', '');
        } else {
            $(this).prop('disabled', 'disabled');
        }
    });
}


// update table cell according to settings
function render_response(data, td, set) {
    let td_class = '';
    let div_class = '';
    let value = Number($(td).attr('value'));

    if (!set['exists']) {
        td_class = 'noexist';
    } else if (set['buy_only']) {
        td_class = 'buy_only';
    } else if (set['circulation'] && set['circulation'] <= 1500000 && set['circulation'] != 0) {
        td_class = 'rare';
    } else if ([10, 20, 50].includes(value)) {
        td_class = 'brass';
    } else if (set['found'] && set['found_by']) {
        td_class = 'found';
    } else {
        td_class = 'exist';
    }

    if (set['ec']) {
        td_class += ' ec';
    } else if (set['checked']) {
        td_class += ' checked';
    }

    /* add or update marker (and name) if found */
    if (set['found'] && set['found_by'] && set['exists']) {
        div_class = set['found_by'];
        $(td).find('div.coin span').html('').html('✔'); }

    /* add/update name */
    if ([201, 202, 203].includes(data['value'])) {

        let c = String(value).substring(2,3);
        if ('name' in data) {

            /* look for div.special123_name */
            let name = escape_html(data['name']);
            let div_special_name = $(td).find('div.special' + c + '_name');
            if (div_special_name.length == 0) {

                /* append div if not found */
                $(td).append('<div class="special' + c + '_name three_lines">' + name + '</div>');

            } else if (div_special_name.length == 1) {

                /* only insert inner html */
                div_special_name.html(name);
            }

        /* remove name */
        } else if (!set['exists']) {
            $(td).find('div.special' + c + '_name').html();
        }
    }

    /* remove marker if not exists */
    if (!set['exists'] || !set['found']) {
        $(td).find('div.coin span').html(''); }

    /* apply td styles */
    $(td).removeClass();
    $(td).addClass('coin ' + td_class);

    /* apply div overlay styles */
    $(td).find('div[type=overlay]').removeClass();
    if (set['exists'] && set['found']) {
        $(td).find('div[type=overlay]').addClass('found ' + div_class); }
}


// save/update global settings
function save_settings() {

    let checkboxes = $('#found, #buy_only, #checked, #ec, #exists').map(function() {
        return { [$(this).prop('id')]: $(this).prop('checked') } }).get();
    for (let box of checkboxes) {
        for (let item in box) { settings[item] = box[item]; }
    }
    settings['exists'] = !settings['exists']

    let found_by = $('#found_by option[selected=selected]').html();
    if (found_by && settings['exists'] && settings['found']) {
        settings['found_by'] = found_by;
    }

    let found_on = $('#found_on').val();
    let pattern = /(\d{2})\.(\d{2})\.(\d{4})/;
    if (!isNaN(found_on) && isNaN(Date.parse(found_on.replace(pattern, '$3-$2-$1')))) {;
        settings['found_on'] = get_datetime();
    } else {
        settings['found_on'] = found_on;
    }

    let circulation = parseInt(String($('#circulation').val()).split('.').join(''));
    if (isNaN(circulation) || circulation < 0 || circulation > 1000000000) {
        settings['circulation'] = 0;
    } else {
        settings['circulation'] = circulation;
    }
}


// begin document.ready
$(document).ready(function() {

    //
    // Buttons
    //


    // go home
    $('thead tr:first-child th').click(function() {
        window.location = './'; });

    // button #begin_edit
    $('#begin_edit').click(function() {
        $('nav.navbar').fadeIn('fast');
        $('#begin_edit').fadeOut('fast');

        // add coin
        $('td.coin').each(function() {
            $(this).css('cursor', 'cell');
            $(this).click(function() {
                save_settings();

                let csrf_token  = $('input[name=csrfmiddlewaretoken]').val();
                let value       = Number($(this).attr('value'));
                let year        = Number($(this).parent('tr').attr('name'));
                year           += (year == 99) ? 1900 : 2000; // TODO fix this before the end of 2098
                let country     = $(this).parents('table').attr('name');
                let stamp       = $(this).parent('tr').attr('stamp');
                let found_by    = (settings['found']) ? settings['found_by'] : ''
                let found_on    = (settings['found']) ? settings['found_on'] : ''
                let circulation = (settings['circulation'] == 'Auflage') ? 0 : settings['circulation']

                if (settings['exists'] === false) { circulation = 0; }

                let data = {
                    csrfmiddlewaretoken: csrf_token,
                    value:       value,
                    year:        year,
                    country:     country,
                    stamp:       stamp,
                    found_by:    found_by,
                    found_on:    found_on,
                    circulation: circulation,
                    buy_only:    settings['buy_only'],
                    checked:     settings['checked'],
                    ec:          settings['ec'],
                    exists:      settings['exists']
                }

                let args = {
                    data: data,
                    td:   this }

                let name = $(this).find('div.special_name').html();
                let input = (name) ? {name: name} : null

                if ([201, 202, 203].includes(value) && data['exists']) {
                    let modal = new Modal('add_coin_name', add_coin_name, args, input);
                    modal.show();
                } else {
                    add_coin_name(args);
                }

                /* make a POST request to ./add/coin */
                function add_coin_name(args, response='') {
                    let data = args['data'];
                    let td = args['td'];
                    if (response) {
                        data['name'] = response['name'].trim().substring(0, 79); }
                    $(td).css('cursor', 'progress');

                    $.ajax({
                        type:     'POST',
                        url:      'add/coin',
                        data:     data,
                        dataType: 'json',
                        td:       td,
                        success:  function(response) {
                            $(td).css('cursor', 'cell');
                            if (response.status === 0) {
                                render_response(data, this.td, settings);
                                detach('add_coin_name');
                            } else {
                                alert(response.message);
                            }
                        }
                    });
                }
            });
        });
    });

    // button #finish_edit
    $('#finish_edit').click(function() {
        $('nav.navbar').fadeOut('fast');
        $('#begin_edit').fadeIn('fast');
        $('td.coin').each(function() {
            $(this).css('cursor', 'default');
            $(this).off('click');
        });
    });

    // button #advanced_options
    $('#show_advanced_options').click(function() {
        $('#advanced_options').slideToggle(); });


    //
    // Misc
    //

    // checkbox #found
    $('#found').change(function() {
        render_found(); });

    // checkbox #exists
    $('#exists').change(function() {

        if (this.checked === true) {

            save_settings();

            // remove values
            $('#found_by, #found_on, #circulation').each(function() {
                $(this).val(''); });

            // disable settings
            $('#found, #buy_only, #checked, #ec').each(function() {
                $(this).prop('checked', false); });
            $('#found, #found_by, #found_on, #circulation, #buy_only, #checked, #ec').each(function() {
                $(this).prop('disabled', 'disabled'); });

        // checkbox #exists not checked
        } else {

            // restore values
            $('#found_by').val(settings['found_by']);
            $('#found_on').val(settings['found_on']);
            $('#circulation').val(settings['circulation']);

            // restore settings
            $('#found_now, #found, #buy_only, #checked, #ec').each(function() {
                let setting = $(this).prop('id');
                $(this).prop('checked', settings[setting]); });

            // enable settings
            $('#found, #found_by, #found_on, #circulation, #buy_only, #checked, #ec').each(function() {
                $(this).prop('disabled', ''); });

            render_found();
        }
    });

    // select username on change
    $('nav.navbar select').on('change', function() {
        let color = $('nav.navbar option[value=' + this.value + ']').attr('color');
        $('nav.navbar option[selected=selected]').removeAttr('selected');
        render_login(this.value, color); });

    // datepicker TODO make it nicer
    $.datepicker.setDefaults( $.datepicker.regional['de'] );
    $('input[name=found_on]').datepicker({
        defaultDate: new Date(),
        dateFormat:  'dd.mm.yy' });

    // modal #add_user
    $('#show_add_user').click(function() {
        let modal = new Modal('add_user', add_user);
        modal.show();

        function add_user(args='', response='') {
            let name  = encodeURIComponent(response['name']
                .trim().substring(0, 19).replace(' ', '-'));
            let color = encodeURIComponent(response['color']
                .trim().substring(0, 9 ).replace(' ', '-'));

            $.ajax({
                type: 'GET',
                dataType: 'json',
                url: 'add/user/' + name + '/color/' + color,
                success: function(response) {

                    if (response.status === 0) {
                        render_login(name, color);
                        detach('add_user');
                    } else {
                        $('#response').html(response.message);
                        $('#response').css('color', 'red');
                    }
                }
            });
        }
    });


    //
    // Main routine
    //

    let cookie = new Cookie();
    let name = cookie.get('coinc-name');
    let color = cookie.get('coinc-color');

    if (name != '' && color != '') {
        render_login(name, color);
    } else {
        name = $('#found_by option:first-child').html();
        color = $('#found_by option:first-child').attr('color');
        render_login(name, color);
    }

    save_settings()
    render_found();

});
