/**
 * Graph full style.
 */

function GraphFullStyle(redrawCallback)
{
    this.version = 1;
    this.edgeCommonStyle         = DefaultCommonEdgeStyle();
    this.isEdgeCommonStyleCustom = false;
    this.edgeSelectedStyles      = FullArrayCopy(DefaultSelectedEdgeStyles);
    this.isEdgeSelectedStylesCustom = false;

    this.vertexCommonStyle          = DefaultCommonVertexStyle();
    this.isVertexCommonStyleCustom  = false;
    this.vertexSelectedVertexStyles = FullArrayCopy(DefaultSelectedGraphStyles);
    this.isVertexSelectedVertexStylesCustom  = false;

    this.backgroundCommonStyle = DefaultCommonBackgroundStyle();
    this.isBackgroundCommonStyleCustom  = false;

    this.defaultVertexSize = 30;
    this.defaultEdgeWidth = 3;
    this.redrawCallback = redrawCallback;
}

GraphFullStyle.prototype.Save = function()
{
    var res = "";
    
    var needEnd    = false;
    var checkValue = [];
    
    checkValue.push({field: "edgeCommonStyle",
                     value: this.edgeCommonStyle,
                     check: this.isEdgeCommonStyleCustom});
    
    checkValue.push({field: "edgeSelectedStyles",
                     value: this.edgeSelectedStyles,
                     check: this.isEdgeSelectedStylesCustom});
    
    checkValue.push({field: "vertexCommonStyle",
                     value: this.vertexCommonStyle,
                     check: this.isVertexCommonStyleCustom});
    
    checkValue.push({field: "vertexSelectedVertexStyles",
                     value: this.vertexSelectedVertexStyles,
                     check: this.isVertexSelectedVertexStylesCustom});
    
    checkValue.push({field: "backgroundCommonStyle",
                     value: this.backgroundCommonStyle,
                     check: this.isBackgroundCommonStyleCustom});

    checkValue.push({field: "defaultVertexSize",
                      value: this.defaultVertexSize,
                      check: this.defaultVertexSize != null}); 

    checkValue.push({field: "defaultEdgeWidth",
                      value: this.defaultEdgeWidth,
                      check: this.defaultEdgeWidth != null});
    
    checkValue.forEach(function(entry) {
            if (!entry.check)
                return;
                
            if (needEnd)
                res = res + ",";

            let valueJson = "";
            if (typeof entry.value.saveToJson === "function") {
                valueJson = entry.value.saveToJson();
            } else {
                valueJson = JSON.stringify(entry.value);
            }
                
                
            res = res + "\"" + entry.field + "\"" + ":" + valueJson;
            needEnd = true;
        });
    
    res = res + "";
    
    return res;
}

GraphFullStyle.prototype.Load = function(json)
{
    var checkValue = [];
    
    checkValue.push({field: "edgeCommonStyle",
                     value: this.edgeCommonStyle,
                     check: "isEdgeCommonStyleCustom",
                     deep: false});
    
    checkValue.push({field: "edgeSelectedStyles",
                     value: this.edgeSelectedStyles,
                     check: "isEdgeSelectedStylesCustom",
                     deep: true});
    
    checkValue.push({field: "vertexCommonStyle",
                     value: this.vertexCommonStyle,
                     check: "isVertexCommonStyleCustom",
                     deep: false});
    
    checkValue.push({field: "vertexSelectedVertexStyles",
                     value: this.vertexSelectedVertexStyles,
                     check: "isVertexSelectedVertexStylesCustom",
                     deep: true});

    checkValue.push({field: "defaultVertexSize",
                    value: "defaultVertexSize",
                    check: null,
                    deep: false});

    checkValue.push({field: "defaultEdgeWidth",
                    value: "defaultEdgeWidth",
                    check: null,
                    deep: false});
    
    checkValue.push({field: "backgroundCommonStyle",
                     value: this.backgroundCommonStyle,
                     check: "isBackgroundCommonStyleCustom",
                     deep: false});
    
    var decoderStr = json;
    var parsedSave = JSON.parse(decoderStr);
    
    var app = this;
    
    checkValue.forEach(function(entry) {
            if (parsedSave.hasOwnProperty(entry.field))
            {
                if (typeof parsedSave[entry.field] === 'number')
                {
                    app[entry.value] = parseInt(parsedSave[entry.field]);
                }
                else
                {
                    if (typeof entry.value.loadFromJson === "function") {
                        entry.value.loadFromJson(parsedSave[entry.field], function () {
                                setTimeout( 
                                    function() 
                                    { 
                                        if (app.redrawCallback != null)
                                        {
                                            app.redrawCallback();
                                        } 
                                    }, 1000);
                            });
                        if (entry.check != null)
                            app[entry.check] = true;
                        return;
                    }

                    if (!entry.deep)
                        entry.value.Clear();

                    //console.log(parsedSave[entry.field]);
                    for(var k in parsedSave[entry.field])
                    {
                        if (!entry.deep)
                        {
                            if (entry.value.ShouldLoad(k))
                            {
                                entry.value[k] = parsedSave[entry.field][k];
                            }
                        }
                        else
                        {
                            // Check is number or not
                            if (k % 1 != 0)
                            {
                                continue;
                            }

                            // Old saves contains more styles. Just skip it.
                            if (entry.value[k] == undefined)
                            {
                                continue;
                            }

                            entry.value[k].Clear();
                            for(var deepK in parsedSave[entry.field][k])
                            {
                                if (k < entry.value.length && entry.value[k].ShouldLoad(deepK))
                                    entry.value[k][deepK] = parsedSave[entry.field][k][deepK];
                            }
                        }
                    }
                }
                
                if (entry.check != null)
                    app[entry.check] = true;
            }
        });
}

GraphFullStyle.prototype.GetVersion = function()
{
    return this.version;
}

GraphFullStyle.prototype.Print = function()
{
    let print_all_fields = function (style)
    {
        for (const [key, value] of Object.entries(style)) {
            console.log(` ${key}:`, value);
        }
    }
    console.log("Graph Full Style:");
    console.log("Edge Common Style: ");
    print_all_fields(this.edgeCommonStyle);
    console.log("Edge Selected Styles:");
    this.edgeSelectedStyles.forEach(function(edge_style, index) {
        console.log(`[${index}]`);
        print_all_fields(edge_style);
    });
    console.log("Vertex Common Style: ");
    print_all_fields(this.vertexCommonStyle);
    console.log("Vertex Selected Styles: ");
    this.vertexSelectedVertexStyles.forEach(function(vertex_style, index) {
        console.log(`[${index}]`);
        print_all_fields(vertex_style);
    });
    console.log("Background Common Style: ");
    print_all_fields(this.backgroundCommonStyle);
}

function OldGraphFullStyle()
{
    GraphFullStyle.apply(this, arguments);

    this.version = 0;
    this.edgeCommonStyle         = GetOldCommonEdgeStyle();
    this.edgeSelectedStyles      = FullArrayCopy(OldSelectedEdgeStyles);

    this.vertexCommonStyle          = GetOldCommonVertexStyle();
    this.vertexSelectedVertexStyles = FullArrayCopy(OldSelectedGraphStyles);

    this.backgroundCommonStyle = GetWhiteBackgroundStyle();

    this.defaultVertexSize = 30;
    this.defaultEdgeWidth = 4;
}

OldGraphFullStyle.prototype = Object.create(GraphFullStyle.prototype);

function NightGraphFullStyle()
{
    GraphFullStyle.apply(this, arguments);

    this.version = 1;
    this.edgeCommonStyle         = GetNightCommonEdgeStyle();
    this.edgeSelectedStyles      = FullArrayCopy(NightSelectedEdgeStyles);

    this.vertexCommonStyle          = GetNightCommonVertexStyle();
    this.vertexSelectedVertexStyles = FullArrayCopy(NightSelectedGraphStyles);

    this.backgroundCommonStyle = GetNightBackgroundStyle();

    this.defaultVertexSize = 30;
    this.defaultEdgeWidth = 3;

    this.isEdgeCommonStyleCustom = true;
    this.isEdgeSelectedStylesCustom = true;

    this.isVertexCommonStyleCustom = true;
    this.isVertexSelectedVertexStylesCustom = true;

    this.isBackgroundCommonStyleCustom = true;
}

NightGraphFullStyle.prototype = Object.create(GraphFullStyle.prototype);

function ContrastGraphFullStyle()
{
    GraphFullStyle.apply(this, arguments);

    this.version = 1;
    this.edgeCommonStyle         = GetContrastCommonEdgeStyle();
    this.edgeSelectedStyles      = FullArrayCopy(ContrastSelectedEdgeStyles);

    this.vertexCommonStyle          = GetContrastCommonVertexStyle();
    this.vertexSelectedVertexStyles = FullArrayCopy(ContrastSelectedGraphStyles);

    this.backgroundCommonStyle = GetWhiteBackgroundStyle();

    this.defaultVertexSize = 36;
    this.defaultEdgeWidth = 4;

    this.isEdgeCommonStyleCustom = true;
    this.isEdgeSelectedStylesCustom = true;

    this.isVertexCommonStyleCustom = true;
    this.isVertexSelectedVertexStylesCustom = true;

    this.isBackgroundCommonStyleCustom = true;
}

ContrastGraphFullStyle.prototype = Object.create(GraphFullStyle.prototype);