/*******************************************************************************
* Copyright (c) 2013 "Filippo Scognamiglio"
* https://github.com/Swordfish90/cool-retro-term
*
* This file is part of cool-retro-term.
*
* cool-retro-term 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 QtQuick 2.2

import "utils.js" as Utils

Item{
    property string version: "0.9"

    // GENERAL SETTINGS ///////////////////////////////////////////////////

    property bool fullscreen: false
    property bool showMenubar: true

    property real windowOpacity: 1.0
    property real ambient_light: 0.2
    property real contrast: 0.85
    property real brightness: 0.5

    property bool show_terminal_size: true
    property real window_scaling: 1.0

    property real fps: 24
    property bool verbose: false

    onWindow_scalingChanged: handleFontChanged();

    // PROFILE SETTINGS ///////////////////////////////////////////////////////

    property string _background_color: "#000000"
    property string _font_color: "#ff8100"
    property string saturated_color: Utils.mix(Utils.strToColor("#FFFFFF"), Utils.strToColor(_font_color), saturation_color * 0.5)
    property color font_color: Utils.mix(Utils.strToColor(saturated_color), Utils.strToColor(_background_color), 0.7 + (contrast * 0.3))
    property color background_color: Utils.mix(Utils.strToColor(_background_color), Utils.strToColor(saturated_color), 0.7 + (contrast * 0.3))

    property real noise_strength: 0.1
    property real screen_distortion: 0.1
    property real glowing_line_strength: 0.2
    property real motion_blur: 0.40
    property real bloom_strength: 0.65

    property real bloom_quality: 0.5
    property real blur_quality: 0.5

    property real chroma_color: 0.0
    property real saturation_color: 0.0

    property real jitter: 0.18

    property real horizontal_sincronization: 0.08
    property real brightness_flickering: 0.1

    property real rgb_shift: 0.0

    readonly property int no_rasterization: 0
    readonly property int scanline_rasterization: 1
    readonly property int pixel_rasterization: 2

    property int rasterization: no_rasterization

    property alias profiles_list: profileslist
    property int profiles_index: 0

    // FONTS //////////////////////////////////////////////////////////////////

    property real fontScaling: 1.0
    property real fontWidth: 1.0

    property var fontNames: ["TERMINUS", "COMMODORE_PET", "COMMODORE_PET"]
    property var fontlist: fontManager.item.fontlist

    signal terminalFontChanged(string fontSource, int pixelSize, int lineSpacing, real screenScaling, real fontWidth)

    Loader{
        id: fontManager

        states: [
            State { when: rasterization == no_rasterization
                PropertyChanges {target: fontManager; source: "Fonts.qml" } },
            State { when: rasterization == scanline_rasterization
                PropertyChanges {target: fontManager; source: "FontScanlines.qml" } },
            State { when: rasterization == pixel_rasterization;
                PropertyChanges {target: fontManager; source: "FontPixels.qml" } }
        ]

        onLoaded: handleFontChanged()
    }

    onFontScalingChanged: handleFontChanged();
    onFontWidthChanged: handleFontChanged();

    function getIndexByName(name) {
        for (var i = 0; i < fontlist.count; i++) {
            if (name === fontlist.get(i).name)
                return i;
        }
        return 0; // If the font is not available returns the first one.
    }

    function incrementScaling(){
        fontScaling = Math.min(fontScaling + 0.05, 2.50);
        handleFontChanged();
    }

    function decrementScaling(){
        fontScaling = Math.max(fontScaling - 0.05, 0.50);
        handleFontChanged();
    }

    function handleFontChanged(){
        if (!fontManager.item) return;

        var index = getIndexByName(fontNames[rasterization]);
        if (index === undefined) return;

        fontManager.item.selectedFontIndex = index;
        fontManager.item.scaling = fontScaling * window_scaling;

        var fontSource = fontManager.item.source;
        var pixelSize = fontManager.item.pixelSize;
        var lineSpacing = fontManager.item.lineSpacing;
        var screenScaling = fontManager.item.screenScaling;
        var fontWidth = fontManager.item.defaultFontWidth * appSettings.fontWidth;

        terminalFontChanged(fontSource, pixelSize, lineSpacing, screenScaling, fontWidth);
    }

    // FRAMES /////////////////////////////////////////////////////////////////

    property bool _frameReflections: false
    property bool reflectionsAllowed: framelist.get(frames_index).reflections
    property bool frameReflections: _frameReflections && reflectionsAllowed

    ListModel{
        id: framelist
        ListElement{text: "No frame"; source: ""; reflections: false}
        ListElement{text: "Simple white frame"; source: "./frames/WhiteSimpleFrame.qml"; reflections: true}
        ListElement{text: "Rough black frame"; source: "./frames/BlackRoughFrame.qml"; reflections: true}
    }

    property string frame_source: frames_list.get(frames_index).source
    property int frames_index: 1
    property alias frames_list: framelist

    // DB STORAGE /////////////////////////////////////////////////////////////

    Storage{id: storage}

    function stringify(obj) {
        var replacer = function(key, val) {
            return val.toFixed ? Number(val.toFixed(4)) : val;
        }
        return JSON.stringify(obj, replacer, 2);
    }

    function composeSettingsString(){
        var settings = {
            fps: fps,
            window_scaling: window_scaling,
            show_terminal_size: show_terminal_size,
            fontScaling: fontScaling,
            fontNames: fontNames,
            frameReflections: _frameReflections,
            showMenubar: showMenubar,
            bloom_quality: bloom_quality,
            blur_quality: blur_quality
        }
        return stringify(settings);
    }

    function composeProfileString(){
        var settings = {
            background_color: _background_color,
            font_color: _font_color,
            brightness_flickering: brightness_flickering,
            horizontal_sincronization: horizontal_sincronization,
            noise_strength: noise_strength,
            chroma_color: chroma_color,
            saturation_color: saturation_color,
            screen_distortion: screen_distortion,
            glowing_line_strength: glowing_line_strength,
            frames_index: frames_index,
            motion_blur: motion_blur,
            bloom_strength: bloom_strength,
            rasterization: rasterization,
            jitter: jitter,
            rgb_shift: rgb_shift,
            brightness: brightness,
            contrast: contrast,
            ambient_light: ambient_light,
            windowOpacity: windowOpacity,
            fontName: fontNames[rasterization],
            fontWidth: fontWidth
        }
        return stringify(settings);
    }

    function loadSettings(){
        var settingsString = storage.getSetting("_CURRENT_SETTINGS");
        var profileString = storage.getSetting("_CURRENT_PROFILE");

        if(!settingsString) return;
        if(!profileString) return;

        loadSettingsString(settingsString);
        loadProfileString(profileString);

        if (verbose)
            console.log("Loading settings: " + settingsString + profileString);
    }

    function storeSettings(){
        var settingsString = composeSettingsString();
        var profileString = composeProfileString();

        storage.setSetting("_CURRENT_SETTINGS", settingsString);
        storage.setSetting("_CURRENT_PROFILE", profileString);

        if (verbose) {
            console.log("Storing settings: " + settingsString);
            console.log("Storing profile: " + profileString);
        }
    }

    function loadSettingsString(settingsString){
        var settings = JSON.parse(settingsString);

        show_terminal_size = settings.show_terminal_size !== undefined ? settings.show_terminal_size : show_terminal_size

        fps = settings.fps !== undefined ? settings.fps: fps
        window_scaling = settings.window_scaling !== undefined ? settings.window_scaling : window_scaling

        fontNames = settings.fontNames !== undefined ? settings.fontNames : fontNames
        fontScaling = settings.fontScaling !== undefined ? settings.fontScaling : fontScaling

        _frameReflections = settings.frameReflections !== undefined ? settings.frameReflections : _frameReflections;

        showMenubar = settings.showMenubar !== undefined ? settings.showMenubar : showMenubar;

        bloom_quality = settings.bloom_quality !== undefined ? settings.bloom_quality : bloom_quality;
        blur_quality = settings.blur_quality !== undefined ? settings.blur_quality : blur_quality;
    }

    function loadProfileString(profileString){
        var settings = JSON.parse(profileString);

        _background_color = settings.background_color !== undefined ? settings.background_color : _background_color;
        _font_color = settings.font_color !== undefined ? settings.font_color : _font_color;

        horizontal_sincronization = settings.horizontal_sincronization !== undefined ? settings.horizontal_sincronization : horizontal_sincronization
        brightness_flickering = settings.brightness_flickering !== undefined ? settings.brightness_flickering : brightness_flickering;
        noise_strength = settings.noise_strength !== undefined ? settings.noise_strength : noise_strength;
        chroma_color = settings.chroma_color !== undefined ? settings.chroma_color : chroma_color;
        saturation_color = settings.saturation_color !== undefined ? settings.saturation_color : saturation_color;
        screen_distortion = settings.screen_distortion !== undefined ? settings.screen_distortion : screen_distortion;
        glowing_line_strength = settings.glowing_line_strength !== undefined ? settings.glowing_line_strength : glowing_line_strength;

        motion_blur = settings.motion_blur !== undefined ? settings.motion_blur : motion_blur
        bloom_strength = settings.bloom_strength !== undefined ? settings.bloom_strength : bloom_strength

        frames_index = settings.frames_index !== undefined ? settings.frames_index : frames_index;

        rasterization = settings.rasterization !== undefined ? settings.rasterization : rasterization;

        jitter = settings.jitter !== undefined ? settings.jitter : jitter;

        rgb_shift = settings.rgb_shift !== undefined ? settings.rgb_shift : rgb_shift;

        ambient_light = settings.ambient_light !== undefined ? settings.ambient_light : ambient_light;
        contrast = settings.contrast !== undefined ? settings.contrast : contrast;
        brightness = settings.brightness !== undefined ? settings.brightness : brightness;
        windowOpacity = settings.windowOpacity !== undefined ? settings.windowOpacity : windowOpacity;

        fontNames[rasterization] = settings.fontName !== undefined ? settings.fontName : fontNames[rasterization];
        fontWidth = settings.fontWidth !== undefined ? settings.fontWidth : fontWidth;
    }

    function storeCustomProfiles(){
        storage.setSetting("_CUSTOM_PROFILES", composeCustomProfilesString());
    }

    function loadCustomProfiles(){
        var customProfileString = storage.getSetting("_CUSTOM_PROFILES");
        if(customProfileString === undefined) customProfileString = "[]";
        loadCustomProfilesString(customProfileString);
    }

    function loadCustomProfilesString(customProfilesString){
        var customProfiles = JSON.parse(customProfilesString);
        for (var i=0; i<customProfiles.length; i++) {
            var profile = customProfiles[i];
            console.log("Loading custom profile: " + stringify(profile));
            profiles_list.append(profile);
        }
    }

    function composeCustomProfilesString(){
        var customProfiles = []
        for(var i=0; i<profileslist.count; i++){
            var profile = profileslist.get(i);
            if(profile.builtin) continue;
            customProfiles.push({text: profile.text, obj_string: profile.obj_string, builtin: false})
        }
        return stringify(customProfiles);
    }

    function loadCurrentProfile(){
        loadProfile(profiles_index);
    }

    function loadProfile(index){
        var profile = profileslist.get(index);
        loadProfileString(profile.obj_string);
    }

    function addNewCustomProfile(name){
        var profileString = composeProfileString();
        profileslist.append({text: name, obj_string: profileString, builtin: false});
    }

    // PROFILES ///////////////////////////////////////////////////////////////

    ListModel{
        id: profileslist
        ListElement{
            text: "Default Amber"
            obj_string: '{"ambient_light":0.2,"background_color":"#000000","bloom_strength":0.65,"brightness":0.5,"brightness_flickering":0.1,"contrast":0.85,"fontName":"TERMINUS","font_color":"#ff8100","frames_index":1,"glowing_line_strength":0.2,"horizontal_sincronization":0.08,"jitter":0.18,"motion_blur":0.4,"noise_strength":0.1,"rasterization":0,"screen_distortion":0.1,"windowOpacity":1,"chroma_color":0,"saturation_color":0,"rgb_shift":0,"fontWidth":1.0}'
            builtin: true
        }
        ListElement{
            text: "Default Green"
            obj_string: '{"ambient_light":0.2,"background_color":"#000000","bloom_strength":0.4,"brightness":0.5,"brightness_flickering":0.1,"contrast":0.85,"fontName":"TERMINUS","font_color":"#0ccc68","frames_index":1,"glowing_line_strength":0.2,"horizontal_sincronization":0.08,"jitter":0.18,"motion_blur":0.45,"noise_strength":0.1,"rasterization":0,"screen_distortion":0.1,"windowOpacity":1,"chroma_color":0,"saturation_color":0,"rgb_shift":0,"fontWidth":1.0}'
            builtin: true
        }
        ListElement{
            text: "Default Scanlines"
            obj_string: '{"ambient_light":0.2,"background_color":"#000000","bloom_strength":0.4,"brightness":0.5,"brightness_flickering":0.1,"contrast":0.85,"fontName":"TERMINUS","font_color":"#00ff5b","frames_index":1,"glowing_line_strength":0.2,"horizontal_sincronization":0.07,"jitter":0.11,"motion_blur":0.4,"noise_strength":0.05,"rasterization":1,"screen_distortion":0.1,"windowOpacity":1,"chroma_color":0,"saturation_color":0,"rgb_shift":0,"fontWidth":1.0}'
            builtin: true
        }
        ListElement{
            text: "Default Pixelated"
            obj_string: '{"ambient_light":0.2,"background_color":"#000000","bloom_strength":0.4,"brightness":0.5,"brightness_flickering":0.1,"contrast":0.85,"fontName":"TERMINUS","font_color":"#ff8100","frames_index":1,"glowing_line_strength":0.2,"horizontal_sincronization":0.1,"jitter":0,"motion_blur":0.45,"noise_strength":0.14,"rasterization":2,"screen_distortion":0.05,"windowOpacity":1,"chroma_color":0,"saturation_color":0,"rgb_shift":0,"fontWidth":1.0}'
            builtin: true
        }
        ListElement{
            text: "Apple ]["
            obj_string: '{"ambient_light":0.2,"background_color":"#000000","bloom_strength":0.5,"brightness":0.5,"brightness_flickering":0.2,"contrast":0.85,"fontName":"APPLE_II","font_color":"#2fff91","frames_index":1,"glowing_line_strength":0.22,"horizontal_sincronization":0.08,"jitter":0.1,"motion_blur":0.65,"noise_strength":0.08,"rasterization":1,"screen_distortion":0.18,"windowOpacity":1,"chroma_color":0,"saturation_color":0,"rgb_shift":0,"fontWidth":1.0}'
            builtin: true
        }
        ListElement{
            text: "Vintage"
            obj_string: '{"ambient_light":0.2,"background_color":"#000000","bloom_strength":0.4,"brightness":0.5,"brightness_flickering":0.54,"contrast":0.85,"fontName":"TERMINUS","font_color":"#00ff3e","frames_index":2,"glowing_line_strength":0.3,"horizontal_sincronization":0.2,"jitter":0.4,"motion_blur":0.75,"noise_strength":0.2,"rasterization":1,"screen_distortion":0.1,"windowOpacity":1,"chroma_color":0,"saturation_color":0,"rgb_shift":0,"fontWidth":1.0}'
            builtin: true
        }
        ListElement{
            text: "IBM Dos"
            obj_string: '{"ambient_light":0.2,"background_color":"#000000","bloom_strength":0.4,"brightness":0.5,"brightness_flickering":0.07,"contrast":0.85,"fontName":"IBM_DOS","font_color":"#ffffff","frames_index":1,"glowing_line_strength":0.13,"horizontal_sincronization":0,"jitter":0.08,"motion_blur":0.3,"noise_strength":0.03,"rasterization":0,"screen_distortion":0.1,"windowOpacity":1,"chroma_color":1,"saturation_color":0,"rgb_shift":0.5,"fontWidth":1.0}'
            builtin: true
        }
        ListElement{
            text: "IBM 3278"
            obj_string: '{"ambient_light":0.1,"background_color":"#000000","bloom_strength":0.15,"brightness":0.5,"brightness_flickering":0,"contrast":0.95,"fontName":"IBM_3278","font_color":"#0ccc68","frames_index":1,"glowing_line_strength":0,"horizontal_sincronization":0,"jitter":0,"motion_blur":0.6,"noise_strength":0,"rasterization":0,"screen_distortion":0.1,"windowOpacity":1,"chroma_color":0,"saturation_color":0,"rgb_shift":0,"fontWidth":1.0}'
            builtin: true
        }
        ListElement{
            text: "Transparent Green"
            obj_string: '{"ambient_light":0.2,"background_color":"#000000","bloom_strength":0.45,"brightness":0.5,"brightness_flickering":0.20,"contrast":0.85,"fontName":"TERMINUS","font_color":"#0ccc68","frames_index":0,"glowing_line_strength":0.16,"horizontal_sincronization":0.05,"jitter":0.20,"motion_blur":0.25,"noise_strength":0.20,"rasterization":0,"screen_distortion":0.05,"windowOpacity":0.60,"chroma_color":0,"saturation_color":0,"rgb_shift":0,"fontWidth":1.0}'
            builtin: true
        }
    }

    function getProfileIndexByName(name) {
        for (var i = 0; i < profileslist.count; i++) {
            if(profileslist.get(i).text === name)
                return i;
        }
        return -1;
    }

    Component.onCompleted: {
        // Manage the arguments from the QML side.
        var args = Qt.application.arguments;
        if (args.indexOf("--verbose") !== -1) {
            verbose = true;
        }
        if (args.indexOf("--default-settings") === -1) {
            loadSettings();
        }

        loadCustomProfiles();

        var profileArgPosition = args.indexOf("--profile");
        if (profileArgPosition !== -1) {
            var profileIndex = getProfileIndexByName(args[profileArgPosition + 1]);
            if (profileIndex !== -1)
                loadProfile(profileIndex);
            else
                console.log("Warning: selected profile is not valid; ignoring it");
        }

        if (args.indexOf("--fullscreen") !== -1) {
            fullscreen = true;
            showMenubar = false;
        }
    }
    Component.onDestruction: {
        storeSettings();
        storeCustomProfiles();
        //storage.dropSettings(); //DROPS THE SETTINGS!.. REMEMBER TO DISABLE ONCE ENABLED!!
    }
}