// Scripting by Oleg Okhotnikov, contact - svoboda200786@gmail.com
let poupup = document.querySelector(".poupup-menu");

let actionsHist = [];
let actionsIndex = -1;

let myUndo = document.getElementById('undo-btn');
let myRedo = document.getElementById('redo-btn');

let group = {groupName: undefined};

myUndo.onclick = function() {  
    if(actionsIndex >= 0){
        undo_redo('undo');        
        actionsIndex--; 
        var ctx = canvas.contextTop;
        ctx.clearRect(0, 0, canvas.width, canvas.height);                    
    }
};
myRedo.onclick = function () {
    if(actionsIndex < actionsHist.length - 1){
        actionsIndex++; 
        undo_redo('redo'); 
        var ctx = canvas.contextTop;
        ctx.clearRect(0, 0, canvas.width, canvas.height);          
    }   
};
function onObjectAdded(obj){
    let item = obj.target; 
    if(!file_loaded || item.clonned){ // в этом условии объекты создаются при загрузке сохраненного файла или клонировании
        let shape_type = /shape.*/.test(item.groupName); // если groupName содержит "shape", то это примитив
        if(shape_type){ // если примитив
            item.parent = item;
            item.parent.added = true; // для составных объектов параметр added задается в functions.js
            // также added задается в controls.js и editor.js в add_image 
            index++;
            item.index = index;
            shape[index] = item;
            item.clonned = false;
            item.groupName = /[a-zA-Z\_]+/.exec(item.groupName) + index; // перезаписываем groupName, добавляя новый индекс       
        }
        if(!item.parent){
            item.parent = item;          
        }
        oldParam(item);         
    }
    else if(!/legend.*/.test(item.groupName)){
        if(item.parent && !item.parent.zoom_size){
            item.parent.zoom_size = zoom_size;         
        }
        if(item.type == "textbox"){
            canvas.setActiveObject(item);
        }       
    }
    if(canvas.isDrawingMode == 1){
        item.groupName = "shape_pencil" + index;
        item.parent = item;
        item.perPixelTargetFind = true;
        item.parent.zoom_size = zoom_size;                 
    }    
    let shape_type = /shape.*/.test(item.groupName); // если groupName shape, то это примитив
    if(shape_type && !item.parent.added){ // если примитив, объект создается после загрузки сцены
        index++;
        item.index = index;
        shape[index] = item;
    }
    shape_type = /shape_img.*/.test(item.groupName);
    if((shape_type || canvas.isDrawingMode == 1) && !item.parent.added){ // если создали картинку или
        // карандашную линию, то есть объекты которые создаются без срабатывания обработчика canvas.on('mouse:down'),
        // записываем в истории тут - для остальных см. controls.js функцию endOfCreating
        item.parent.added = true;
        oldParam(item);
        changes(item, "4");     
        actionsHist[actionsIndex].flag = 'add';        
        actionsHist.index = item.index; 
    } 
    // возможно так будет быстрее, чем через groupName, потому что в последнем применяется регулярка (пока реализовано только в геометрических ф-ях)
    item.groupType = /[a-zA-Z\_]+/.exec(item.groupName)[0];
}
function onObjectSelected(obj){
    let item = obj.target;
//     // выделена или нажата группа
    if(item != undefined){
        if(item.type == "activeSelection"){ // объект является выделением
            item.hasControls = false;
            item.lockScalingX = true;
            item.lockScalingY = true;            
            item.lockRotation = true; 
            item.parent.zoom_size = item._objects[0].parent.zoom_size; 
        }
        if(canvas.isDrawingMode == 0 && item != null && (item.type != "activeSelection" || item.shapes == 1) ){ 
            if(palette.active){
                palette.active.classList.remove("color-cell-active");        
            }    

            palette.active = document.querySelector("[color='" + item.parent.stroke + "']") || document.querySelector("[color='" + item.parent.fill + "']");
            
            if(palette.active){
                palette.active.classList.add("color-cell-active");                
            }
            
            if(item.parent && item.parent.zoom_size != undefined){
                var size = item.parent.zoom_size + 1;
                setTimeout(function(){
                    scale_indicator.setAttribute("scale_value", size + "x");                       
                }, 10);
                                    
            }            
        }  
    }
}
function calcObjects(item, obj){
    let prop = "_objects";
    let array = obj[prop];
    for(var i = 0; i < array.length; i++){
        item.objects_temp.push(array[i]);
        if(array[i][prop] != undefined){
            calcObjects(item, array[i]);
        }             
    }  
}

function changes(item, num){
    if(item.index != undefined || item.type == "activeSelection" ){
        //console.log("num: " + num);        
        actionsIndex++;       
        actionsHist.splice(actionsIndex, actionsHist.length - actionsIndex);
        histAdd(item);          
    }
    group.param_saved = false;
}

function onObjectModified(obj){
    if(!/back/.test(obj.target.groupName) && !/legend/.test(obj.target.groupName)){
        changes(obj.target, "2");             
    }
}

function onObjectRemoved(item){
    if(item != undefined){
        changes(item, "3");      
        actionsHist.index = item.index;    
    }    
}
function onSelectionCleared(item){
    if(typeof selection_temp2 != "undefined" && selection_temp2 ){
        var line = item.deselected[0].parent;
        line.x1 = line.arrow.left;
        line.y1 = line.arrow.top;
        line.x2 = line.arrow2.left;
        line.y2 = line.arrow2.top;        
        selection_temp2 = null;                      
    }
    poupup.classList.add("mfp-hide");
}
document.addEventListener("click", function(e){
// алгоритм для выделения нескольких объектов находится в fabric.js      
    let item = canvas.getActiveObject();
    if(item != undefined && item.type == "activeSelection"){
        item.parent = item;
        // oldParam(item);      
    }
    if(e.target.className == "upper-canvas " && !move_flag && item != undefined
        && item.parent.objects != undefined && item.type != "i-text"){
    }
    else if(move_flag){
        let obj = {};
        obj.target = item;       
        // onObjectSelected(obj);       
    }
    move_flag = false;
});
canvas.on('mouse:down:before', function(e){
    var obj = e.target;
    if(obj && editor_command || text_editing){
        drawing_object = true;
    }
    if(obj){
        if(drawing_object){
            let array = obj.parent.objects;
            for(var i in array){            
                obj.parent[array[i]].selectable = false;
            } 
        }
        else{
            let array = obj.parent.objects;          
            for(var i in array){
                var name = obj.parent[array[i]].name;
                if( (name == "rect" && obj.parent[array[i]].groupType == "socket")
                    || name == "arrow" || name == "arrow2" || name == "arrow_part1" || name == "arrow_part2" || name == "line"){
                    obj.parent[array[i]].selectable = true;                 
                }             
            } 
        }
    }
    if(group.cloneOne){ // __onMouseDown в fabric.js, там установлен getActiveObject().setCoords()
        let item = canvas.getActiveObject();       
        editor_obj.setClone(item);
        // item.hasControls = true;
        // canvas.setActiveObject(item);
        canvas.renderAll(); 
        element_cursor();        
    }       
});
canvas.on('selection:created', onObjectSelected);
canvas.on('selection:updated', onObjectSelected);
canvas.on('selection:cleared', onSelectionCleared);
canvas.on('mouse:down', onObjectSelected);
canvas.on('object:modified', onObjectModified);
canvas.on('object:changed', onObjectModified);
canvas.on('object:added', onObjectAdded);
///////////////////////////////// oldParam /////////////////////////////////
/* Записывает в свойства с посфиксом old текущие значения - при отмене в них можно будет вернуться */
// Параметр old нужен потому, что предыдущее действик могло быть с другим объектом, поэтому
// нельзя просто взять старое свойство из actionIndex -1
function oldParam(item){
    if (item != null){
        let shape_type = /shape.*/.test(item.groupName);       
        if(item.parent.objects || item.parent._objects){
            if(item.type == "activeSelection"){
                var group_deltaX = item.width / 2 + item.left; // у объектов в группе отсчет координат относительно центра выделения
                var group_deltaY = item.height / 2 + item.top; // у объектов в группе отсчет координат относительно центра выделения                    
                var prop = "_objects";
            }
            else{
                var group_deltaX = 0;
                var group_deltaY = 0;                    
                var prop = "objects";                
            } 
            let array = item.parent[prop]; // записываем части составного объекта в массив
            for(var i in array){
                if(item.type == "activeSelection"){ // у объектов в группе отсчет координат относительно центра выделения
                    var obj = array[i];  
                }
                else{
                    var obj = item.parent[array[i]];                                       
                } 
                obj.set({
                    "x1_old": obj.x1,
                    "x2_old": obj.x2,
                    "y1_old": obj.y1,
                    "y2_old": obj.y2,        
                    "left_old": obj.left + group_deltaX,
                    "top_old": obj.top + group_deltaY,
                    "width_old": obj.width,
                    "height_old": obj.height,                    
                    "originX_old": obj.originX,
                    "originY_old": obj.originY,                    
                    "scaleX_old": obj.scaleX,
                    "scaleY_old": obj.scaleY,
                    "angle_old": obj.angle,
                    "text_old": obj.text,
                    "fill_old": obj.fill,
                    "fontWeight_old": obj.fontWeight,
                    "fontSize_old": obj.fontSize,
                    "stroke_old": obj.stroke,                                     
                    "strokeWidth_old": obj.strokeWidth,
                    "visible_old": obj.visible,
                    "zoom_size_old": obj.zoom_size                                       
                })                    
            }         
        }
        else{
            if(item.x1){
                item.set({ 
                    "x1_old": item.x1,
                    "x2_old": item.x2,
                    "y1_old": item.y1,
                    "y2_old": item.y2
                })
            }
            item.set({                
                "left_old": item.left,
                "top_old": item.top,
                "width_old": item.width,
                "height_old": item.height,        
                "originX_old": item.originX,
                "originY_old": item.originY,        
                "scaleX_old": item.scaleX,
                "scaleY_old": item.scaleY,
                "angle_old": item.angle,
                "text_old": item.text,
                "fill_old": item.fill,
                "fontWeight_old": item.fontWeight,
                "fontSize_old": item.fontSize,
                "stroke_old": item.stroke,                
                "strokeWidth_old": item.strokeWidth,
                "visible_old": item.visible,
                "zoom_size_old": item.zoom_size 
            })          
        }       
    }
}
///////////////////////////////// histAdd /////////////////////////////////
/* Добавляет в историю объект, с текущими параметрами объекта fabric */
function histAdd(item){
    if (item != undefined){
        let shape_type = /shape.*/.test(item.groupName); 
            // Пушим в историю все составные части    
            if(!shape_type || item.type == "activeSelection"){ // если не примитив     
                actionsHist.push([]); // создаем новый элемент в истории

                if(item.type == "activeSelection"){
                    var group_deltaX = item.width / 2 + item.left; // у объектов в группе отсчет координат относительно центра выделения
                    var group_deltaY = item.height / 2 + item.top; // у объектов в группе отсчет координат относительно центра выделения                    
                    var prop = "_objects";
                }
                else{
                    var group_deltaX = 0;
                    var group_deltaY = 0;                    
                    var prop = "objects";                
                } 
                        
                let array = item.parent[prop]; // записываем части составного объекта в массив
                let actionsHistEl = actionsHist[actionsHist.length-1]; // даем новому эелементу истории название
                // actionsHistEl.objects = []; // в это свойсто будут записываться старые и текущие параметры части
                // составного объекта

                for(var i in array){
                    if(item.type == "activeSelection"){ // у объектов в группе отсчет координат относительно центра выделения
                        var obj = array[i];  
                    }
                    else{
                        var obj = item.parent[array[i]];                                       
                    } 
                    actionsHistEl.push({
                        "name": obj.name,             
                        "index": obj.parent.index,        
                        "left_old": obj.left_old,
                        "top_old": obj.top_old,
                        "width_old": obj.width_old,
                        "height_old": obj.height_old,                    
                        "originX_old": obj.originX_old,
                        "originY_old": obj.originY_old,
                        "scaleX_old": obj.scaleX_old,
                        "scaleY_old": obj.scaleY_old,
                        "angle_old": obj.angle_old,
                        'x1_old': obj.x1_old,
                        'y1_old': obj.y1_old,
                        'x2_old': obj.x2_old,
                        'y2_old': obj.y2_old,
                        "text_old": obj.text_old,
                        "fill_old": obj.fill_old,
                        "fontWeight_old": obj.fontWeight_old,
                        "fontSize_old": obj.fontSize_old,
                        "stroke_old": obj.stroke_old,                                           
                        "strokeWidth_old": obj.strokeWidth_old,
                        "visible_old": obj.visible_old,
                        "zoom_size_old": obj.zoom_size_old,                                           
                        "left": obj.left + group_deltaX,
                        "top": obj.top + group_deltaY,
                        "width": obj.width,
                        "height": obj.height,                    
                        "originX": obj.originX,
                        "originY": obj.originY,                    
                        "scaleX": obj.scaleX,
                        "scaleY": obj.scaleY,
                        "angle": obj.angle,
                        'x1': obj.x1,
                        'y1': obj.y1,
                        'x2': obj.x2,
                        'y2': obj.y2,
                        "text": obj.text,
                        "fill": obj.fill,
                        "fontWeight": obj.fontWeight,
                        "fontSize": obj.fontSize,
                        "stroke": obj.stroke,                                       
                        "strokeWidth": obj.strokeWidth,
                        "visible": obj.visible,
                        "zoom_size": obj.zoom_size                                                           
                    }); 
                }        
            }
            else{
                actionsHist.push([]); // создаем новый элемент в истории

                let actionsHistEl = actionsHist[actionsHist.length-1];
                actionsHistEl.push({
                    "index": item.index,        
                    "left_old": item.left_old,
                    "top_old": item.top_old,
                    "width_old": item.width_old,
                    "height_old": item.height_old,            
                    "scaleX_old": item.scaleX_old,
                    "scaleY_old": item.scaleY_old,
                    "originX_old": item.originX_old,
                    "originY_old": item.originY_old,             
                    "angle_old": item.angle_old,
                    "text_old": item.text_old,
                    "fill_old": item.fill_old,
                    "fontWeight_old": item.fontWeight_old,
                    "fontSize_old": item.fontSize_old,
                    "stroke_old": item.stroke_old,                                         
                    "strokeWidth_old": item.strokeWidth_old,
                    "visible_old": item.visible_old,
                    "zoom_size_old": item.zoom_size_old,                                                     
                    "left": item.left,
                    "top": item.top,
                    "width": item.width,
                    "height": item.height,            
                    "originX": item.originX,
                    "originY": item.originY,            
                    "scaleX": item.scaleX,
                    "scaleY": item.scaleY,
                    "angle": item.angle,
                    "text": item.text,
                    "fill": item.fill,
                    "fontWeight": item.fontWeight,
                    "fontSize": item.fontSize,
                    "stroke": item.stroke,                                 
                    "strokeWidth": item.strokeWidth, 
                    "visible": item.visible,
                    "zoom_size": item.zoom_size                                              
                });
            }      
    } 
}

///////////////////////////////// undo_redo /////////////////////////////////
/* Возврат - повтор */
function undo_redo(flag){  
    if(Boolean(actionsHist[actionsIndex])){
        // let item = shape[actionsHist[actionsIndex].index];
        for (var obj of actionsHist[actionsIndex]){
            if(obj.name){
                var item = shape[obj.index][obj.name];
            }
            else{
                var item = shape[obj.index];                
            }
            if(actionsHist[actionsIndex].flag == "add" && flag == 'undo'){ // если объект был создан в этот момент истории
                deleteObj(item, true);
            } 
            else{
                canvas.discardActiveObject();
                canvas.requestRenderAll();            
                if(flag == 'undo'){ 
                    setHistoryParam(item, "_old", obj);
                }
                else{
                    setHistoryParam(item, "", obj);
                }             
            }             
        }
         
        // shape[actionsHist[actionsIndex].index].setCoords();               
    }
    canvas.discardActiveObject().renderAll(); 
}
///////////////////////////////// setHistoryParam /////////////////////////////////
/* Устанавливает значения , записанные при помощи oldParam */
function setHistoryParam(item, postfix, obj){         
    if(item.name){
        item.set({
            "x1": obj["x1" + postfix],
            "x2": obj["x2" + postfix],
            "y1": obj["y1" + postfix],
            "y2": obj["y2" + postfix],                            
            "left": obj["left" + postfix],
            "top": obj["top" + postfix],
            "width": obj["width" + postfix],
            "height": obj["height" + postfix],                
            "originX": obj["originX" + postfix],
            "originY": obj["originY" + postfix],                
            "scaleX": obj["scaleX" + postfix],
            "scaleY": obj["scaleY" + postfix],
            "angle": obj["angle" + postfix],
            "text": obj["text" + postfix],
            "fill": obj["fill" + postfix],
            "fontWeight": obj["fontWeight" + postfix],
            "fontSize": obj["fontSize" + postfix],
            "stroke": obj["stroke" + postfix],                                
            "strokeWidth": obj["strokeWidth" + postfix],
            "visible": obj["visible" + postfix],
            "zoom_size": obj["zoom_size" + postfix]                               
        });           
        item.setCoords();                              
    }
// Примитивы:
// Если выделено несколько объектов, втом числе составных,
// то все будут расчитываться как сумма примитиввов, потому что обсчет идет
// для item, в который записывается результат canvas.getActiveObject() - это будет выделение
// или (activeSelection)
    else{            
        item.set({
            "left": obj["left" + postfix],
            "top": obj["top" + postfix],
            "width": obj["width" + postfix],
            "height": obj["height" + postfix],            
            "originX": obj["originX" + postfix],
            "originY": obj["originY" + postfix],           
            "scaleX": obj["scaleX" + postfix],
            "scaleY": obj["scaleY" + postfix],
            "angle": obj["angle" + postfix],
            "text": obj["text" + postfix],            
            "fill": obj["fill" + postfix],
            "fontWeight": obj["fontWeight" + postfix],
            "fontSize": obj["fontSize" + postfix],
            "stroke": obj["stroke" + postfix],            
            "strokeWidth": obj["strokeWidth" + postfix],
            "visible": obj["visible" + postfix],
            "zoom_size": obj["zoom_size" + postfix]                       
        });
        shape_type = /shape_svg.*/.test(item.groupName);
        if(shape_type){
            editor_obj.add_legend();
        } 
        canvas.renderAll(); 
    }
    // if(item.parent._objects != undefined){ // выделение или группа
    //     setHistoryParam_subfunction(item, postfix);
    // }    
}
function setHistoryParam_subfunction(item, postfix, array){
/* подфункция для объектов, создаваемых с помощью выделения или группы */
    // if(shape[actionsHist[actionsIndex].index].type == "activeSelection"){
    //     var obj = shape[actionsHist[actionsIndex].index].objects_temp; 
    // }
    // else{
        var obj = shape[actionsHist[actionsIndex].index]._objects;         
    // }        
    if(array == undefined){
        var array = actionsHist[actionsIndex]["_objects"];     
    }
    for(var i in array){
        obj[i].set({
            "fill": array[i]["fill" + postfix],
            "fontWeight": array[i]["fontWeight" + postfix],
            "fontSize": array[i]["fontSize" + postfix],
            "stroke": array[i]["stroke" + postfix],                                 
            "strokeWidth": array[i]["strokeWidth" + postfix],
            "scaleX": array[i]["scaleX" + postfix],
            "scaleY": array[i]["scaleY" + postfix],                                          
            "visible": array[i]["visible" + postfix],
            "zoom_size": array[i]["zoom_size" + postfix]                                           
        });
        shape_type = /shape_svg.*/.test(obj[i].groupName);
        if(shape_type){
            editor_obj.add_legend();
        }                         
    } 
}
