let colors_html = $("#color_samples_fill div.col").clone();
$("#color_samples_stroke").append(colors_html);

let cnv, buff, buff2, bg;
let W, H, rad;
let t = 0;
let mouse_down = 0;
let first_load = 1;
let bgCheck = 1;
let bg_color = "#ffffff";
let erase_color = "#fff";
let stroke_color = "#00ccee";
let stroke_weight = 2;
let fill_color = (init_fill_color = "#ffcc22");
let fillCheck = (strokeCheck = 1);
let isActive;
let tool = "";
let points = [];
let endX = (endY = 0);
let signX = (signY = 1);
let oldX = (oldY = controlX = controlY = 0);
let step = 15;
let square_bg;
let counter = (counter2 = 0);
let current_undo = 0
let current_draw = 0
let undo_states = []
let force_undo = force_redo = 0;
let bgImage;
let imageLoaded = 0;
let smooth_val = 0;
let visibleText = 0;
let textX = (textY = txtAreaX = txtAreaY = 0);
let font_size = 32;
let submitText = 0;
let confirmation = 0;
let isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);

// Blur fix for Safari 1/3 (smooth edges effect didn't work in safari)
// Fix requires modification in 3 different points in "painting_script.js" (search this file for "Blur fix for Safari")
// and also the updated "p5.min.js" (the 1033 KB version or a latest one)
const isSafari = 
navigator.vendor &&
navigator.vendor.indexOf('Apple') > -1 &&
navigator.userAgent.indexOf('CriOS') == -1 &&
navigator.userAgent.indexOf('FxiOS') == -1;

// For preserving aspect ratio on resize canvas
let main_aspect_ratio = 640/950

W = $("#canvas_wrapper").width();
H = $("#inner_container").height();

cnv_wrapper = document.getElementById("canvas_wrapper");

function preload() {
    if (imgData.length < 1) {
        FIX_IMAGE = 0;
    }

    if (FIX_IMAGE) {
        bgImage = loadImage(
        imgData,
        () => {
            imageLoaded = 1;
            $(".bg_fill").empty();
        },
        () => {
            FIX_IMAGE = 0;
        }
        ); // p5js loadImage() function
    }
}

function setup() {

    for(a=0; a<=UNDO_LEVELS; a++){
        undo_cnv = createGraphics(W, H);
        undo_cnv.parent(cnv_wrapper);
        undo_cnv.id("undo_" + a);
        undo_cnv.style("position: absolute");

        undo_states.push(undo_cnv)
    }

    bg = createGraphics(W, H);
    bg.parent(cnv_wrapper);
    bg.id("background_canvas");
    bg.show();
    bg.style("position: absolute; z-index:40");

    cnv = createCanvas(W, H, cnv);
    cnv.parent(cnv_wrapper);
    rectMode(CORNERS);
    cnv.style("position: absolute; z-index:100");

    buff = createGraphics(W, H);
    buff.parent(cnv_wrapper);
    buff.id("buff");
    buff.rectMode(CORNERS);
    buff.show();
    buff.style("position: absolute; z-index:150");

    buff2 = createGraphics(W, H);
    buff2.parent(cnv_wrapper);
    buff2.id("buff2");
    buff2.show();
    buff2.style("position: absolute; z-index:200");

    buff.textAlign(LEFT, TOP);

    clear();
    noStroke();
    fill(fill_color);

    undo_states[0].clear()
    undo_states[0].image(cnv, 0, 0);
}

function draw() {
    if (bgCheck) {
        with (bg) {
            clear();

            if (imageLoaded) {
                bg.image(
                bgImage,
                0,
                0,
                width,
                height,
                0,
                0,
                bgImage.width,
                bgImage.height
                );
            } else {
                background(bg_color);
            }
        }
    } else {
        with (bg) {
            clear();
            background(200);
            noStroke();
            counter = 0;

            for (let x = 0; x < width; x += step) {
                counter++;
                counter2 = 0;
                for (let y = 0; y < height; y += step) {
                    counter2++;
                    square_bg = (counter + counter2) % 2 == 0 ? 220 : 250;
                    fill(square_bg);
                    square(x, y, step);
                }
            }
        }
    }

    if (tool == "pencil" || tool == "eraser") {
        with (buff2) {
            clear();
            noFill();
            stroke(20);
            if (tool == "pencil") {
                fill(stroke_color);
            }
        }
        buff2.circle(mouseX, mouseY, stroke_weight);
    }

    if (mouse_down) {
        rad = dist(mouseX, mouseY, points[0][0], points[0][1]);

        if (tool == "pencil" || tool == "eraser") {
            buff.strokeWeight(stroke_weight);
            buff.stroke(stroke_color);

            if (tool == "eraser") {
                erase_color = bgCheck ? bg_color : "#fff";
                buff.stroke(erase_color);
            }
            endX =
                keyIsDown(CONTROL) &&
                abs(mouseY - controlY) > abs(mouseX - controlX)
                ? controlX
                : mouseX;
            endY =
                keyIsDown(CONTROL) &&
                abs(mouseX - controlX) > abs(mouseY - controlY)
                ? controlY
                : mouseY;

            buff.line(oldX, oldY, endX, endY);

            if (abs(endX - oldX) > 0) {
                oldX = endX;
            }
            if (abs(endY - oldY) > 0) {
                oldY = endY;
            }
        } else if (tool == "circle" || tool == "box") {
            with (buff) {
                clear();
                fillCheck ? fill(fill_color) : noFill();
                strokeCheck ? stroke(stroke_color) : noStroke();
                strokeWeight(stroke_weight);
            }

            if (tool == "circle") {
                buff.circle(points[0][0], points[0][1], 2 * rad);
            } else {
                // rectangle
                signX = mouseX < points[0][0] ? -1 : 1;
                signY = mouseY < points[0][1] ? -1 : 1;
                //rad = abs(mouseX - points[0][0])
                endX = keyIsDown(CONTROL) ? points[0][0] + signX * rad : mouseX;
                endY = keyIsDown(CONTROL) ? points[0][1] + signY * rad : mouseY;
                buff.rect(points[0][0], points[0][1], endX, endY);
            }
        } else if (tool == "line") {
            with (buff) {
                clear();
                noFill();
                stroke(stroke_color);
                strokeWeight(stroke_weight);
            }

            endX =
                keyIsDown(CONTROL) &&
                abs(mouseY - points[0][1]) > abs(mouseX - points[0][0])
                ? points[0][0]
                : mouseX;
            endY =
                keyIsDown(CONTROL) &&
                abs(mouseX - points[0][0]) > abs(mouseY - points[0][1])
                ? points[0][1]
                : mouseY;

            buff.line(points[0][0], points[0][1], endX, endY);
        } else if (tool == "text") {
            buff2.stroke("#000");
            buff2.fill("#eee");
            buff2.textSize(14);
            buff2.text("T", textX, textY);
        }
    }

    if (tool == "text" && visibleText) {
        font_size = int($("#font_size").val());
        buff.textLeading(font_size * 1.05);
        buff.textSize(font_size);

        with (buff) {
            clear();
            fill(fill_color);
            noStroke();
        }

        buff.text($("#text_input").val(), textX, textY, width - textX);
    }

    if (tool == "text") {
        $("canvas").css({ cursor: "text" });
    } else {
        $("canvas").css({ cursor: "default" });
    }
}

function mouse_pressed(e = null) {
    if (e != undefined && e.target.id == buff2.id()) {
        mouse_down = 1;
    }

    points[0] = [mouseX, mouseY];
    oldX = mouseX;
    oldY = mouseY;

    if (mouse_down && tool == "text") {
        buff2.clear();

        scale = $("#buff").width() / buff.width;
        textX = mouseX;
        textY = mouseY;

        txtAreaX = mouseX * scale;
        txtAreaY = mouseY * scale + 35;

        if (txtAreaX + $("#text_input_wrapper").width() > width * scale) {
            txtAreaX -= txtAreaX + $("#text_input_wrapper").width() - width * scale;
        }

        if (
        txtAreaY + $("#text_input_wrapper").outerHeight() >
        height * scale
        ) {
            txtAreaY -= $("#text_input_wrapper").outerHeight() + 35;
        }

        $("#text_input_wrapper").css({
            display: "flex",
            left: txtAreaX + "px",
            top: txtAreaY + "px",
        });
        visibleText = 1;

        setTimeout(() => {
            $("#text_input").focus();
        }, 500);
    }
}

function touchStarted(event) {
    if(isMobile) {
        mouse_pressed(event);
    }
}
function touchEnded() {
    if(isMobile) {
        mouse_released();
    }
}
$("#canvas_wrapper").on("mousedown", function(e) {
    mouse_pressed(e);
});
$("#canvas_wrapper").on("mouseup", function(e) {
    mouse_released();
});

// Text fixed
function mouseReleased() {
   mouse_released(); 
}

function mouse_released() {
    oldX = mouseX;
    oldY = mouseY;

    if ((mouse_down && tool && tool != "text") || submitText) {

        if (tool == "eraser") {
            blendMode(REMOVE);
        } else {
            blendMode(BLEND);
        }

        if (submitText) {
            buff.text($("#text_input").val(), textX, textY, width - textX);
        }

        if (smooth_val > 0 && (isSafari || isMobile)) {  // Blur fix for Safari 2/3
            buff.filter(BLUR, smooth_val);
        }

        image(buff, 0, 0);

        blendMode(BLEND);

        current_undo++ 
        if(current_undo > UNDO_LEVELS){
            for(a=0; a<=(UNDO_LEVELS-1); a++){
                undo_states[a].clear()
                undo_states[a].image(undo_states[a+1], 0, 0);
            }
            current_undo = UNDO_LEVELS
        }
         
        current_draw = current_undo

        //$('#title h1').text(current_undo)
        undo_states[current_undo].clear()
        undo_states[current_undo].image(cnv, 0, 0);
        update_undo_buttons()
    }
    mouse_down = 0;

    buff.clear();

    if (submitText) {
        submitText = 0;
        setTimeout(() => {
            hide_text();
            buff.clear();
            buff2.clear();

            mouse_down = 1;
            setTimeout(() => {
                buff2.clear();
                $("#pencil").click();
                $("#pencil")
                .removeClass("active")
                .removeClass("selected")
                .attr("aria-pressed", "false");
                tool = "";
            }, 400);
        }, 200);
    }
}

keyPressed = () => {
    if (tool == "text") {
        if (keyCode === ESCAPE) {
            hide_text();
        }
        buff.clear();
    }

    if (!visibleText) {
        if ((keyIsDown(CONTROL) && keyCode == 90) || force_undo || force_redo) {
            if(keyIsDown(SHIFT) || force_redo) {
                current_undo++
                if(current_undo > current_draw){
                   current_undo = current_draw
                }

                if(current_undo > UNDO_LEVELS){
                    current_undo = UNDO_LEVELS
                }
                force_redo = 0
            }else{
                current_undo--
                if(current_undo < 0){
                    current_undo = 0
                }
                force_undo = 0;                
            }

            clear();
            image(undo_states[current_undo], 0, 0);
            update_undo_buttons()
        }

        if (keyCode === CONTROL) {
            controlX = mouseX;
            controlY = mouseY;
        }

        if (keyCode == 70) {
            // 70 => F toggle the fill checkbox
            $("#fillCheck").click();
        }

        if (keyCode == 71) {
            // 71 => G toggle background
            $("#bgCheck").click();
        }

        if (keyCode == 66) {
            // 66 => B toggle the stroke (border) checkbox
            $("#strokeCheck").click();
        }

        if (keyCode >= 49 && keyCode <= 53) {
            // 49-53 => numbers 1 to 5. Activate relative stroke weight buttons
            $("#stroke_weight button")
                .eq(keyCode % 49)
                .click()
                .addClass("active");
        }

        if (keyCode == 83) {
            // 83 => S Save canvas
            $("#save").click();
        }

        if (keyCode == 68) {
            // 68 => D Delete, clears all canva's content
            mouse_down = 0;
            $("#clear").click();
            buff2.clear();
        }

        if (keyCode == 67) {
            // 67 => C toggle circle
            mouse_down = 0;
            $("#circle").click();
            buff2.clear();
        }

        if (keyCode == 69) {
            // 69 => Ε toggle eraser
            mouse_down = 0;
            $("#eraser").click();
            buff2.clear();
        }

        if (keyCode == 76) {
            // 76 => L toggle line
            $("#line").click();
            buff2.clear();
        }

        if (keyCode == 80) {
            // 80 => P toggle pencil
            mouse_down = 0;
            $("#pencil").click();
            buff2.clear();
        }

        if (keyCode == 82) {
            // 82 => R toggle rectangle, square
            mouse_down = 0;
            $("#box").click();
            buff2.clear();
        }

        if (keyCode == 84) {
            // 84 => T toggle text button
            $("#text").click();
            buff2.clear();
        }
    }
};

function hide_text() {
    $("#text_input_wrapper").hide();
    visibleText = 0;
    mouse_down = 0;
    buff2.clear();
}

$("#cancel_text").click(function () {
    hide_text();
});

$("#submit_text").click(function () {
    submitText = 1;
    mouseReleased();
});

function resize_canvas() {
    W = $("#canvas_wrapper").width();
   /* if (KEEP_MAIN_ASPECT) {
        H = (W*main_aspect_ratio); // based on main aspect
    } else {
        H = $("#inner_container").height();
    }*/
    H = $("#canvas_wrapper").fullScreen() ? min(W*(9/16), screen.height) : (W*main_aspect_ratio)

    if (first_load) {
        if (FIX_IMAGE) {
            preload();
        }

        resizeCanvas(W, H, true);
        buff.resizeCanvas(W, H, true);
        buff2.resizeCanvas(W, H, true);
        bg.resizeCanvas(W, H, true);

        for(a=0; a<=UNDO_LEVELS; a++){
            undo_states[a].resizeCanvas(W, H, true);
        }

        with (cnv) {
            clear();
            redraw();
        }
        first_load = 0;
    }

    cnv.style(`width: ${W}px; height: ${H}px`);
    buff.style(`width: ${W}px; height: ${H}px`);
    buff2.style(`width: ${W}px; height: ${H}px`);
    bg.style(`width: ${W}px; height: ${H}px`);

    for(a=0; a<=UNDO_LEVELS; a++){
        undo_states[a].style(`width: ${W}px; height: ${H}px`);;
    }
}

function save_canvas() {
    let format = "jpg";

    if (!bgCheck) {
        bg.clear();
        format = "png";
    }

    bg.image(cnv, 0, 0);
    saveCanvas(bg, "image_" + floor(new Date().getTime() / 1000), format);
}

function update_undo_buttons() {
    if(current_undo >= current_draw || current_undo >= UNDO_LEVELS){
       $('#redo').removeClass('btn-primary bg-petrol').addClass('btn-secondary').attr('disabled', true)
    }else{
       $('#redo').removeClass('btn-secondary').addClass('btn-primary bg-petrol').attr('disabled', false)
    }

    if(current_undo <= 0){
       $('#undo').removeClass('btn-primary bg-petrol').addClass('btn-secondary').attr('disabled', true)
    }else{
       $('#undo').removeClass('btn-secondary').addClass('btn-primary bg-petrol').attr('disabled', false)
    }
}

// -------- Fill controls
$("#fillCheck").change(function () {
    fillCheck = $(this).is(":checked");
    if (!fillCheck) {
        $("#strokeCheck").prop("checked", true).change();
    }
});

$("#fillColor").on("input change click", function () {
    $("#color_samples_fill button").removeClass("active");
    init_fill_color = $(this).val();
    fill_color = init_fill_color;
});

$("#color_samples_fill button").click(function () {
    $("#color_samples_fill button").removeClass("active");
    $(this).addClass("active");

    init_fill_color = $(this).data("color");
    fill_color = init_fill_color;
});

// -------- Stroke controls
$("#strokeCheck").change(function () {
    strokeCheck = $(this).is(":checked");
    if (!strokeCheck) {
        $("#fillCheck").prop("checked", true).change();
    }
});

$("#strokeColor").on("input change click", function () {
    $("#color_samples_stroke button").removeClass("active");
    stroke_color = $(this).val();
});

$("#color_samples_stroke button").click(function () {
    $("#color_samples_stroke button").removeClass("active");
    $(this).addClass("active");

    stroke_color = $(this).data("color");
});

$("#stroke_weight button").click(function () {
    $("#stroke_weight  button").removeClass("active");
    $(this).addClass("active");

    stroke_weight = $(this).data("weight");
});

// -------- Bg Fill controls
$("#removeImage").hide();

function updateImageButtons() {
    let buttonTitle = "ΕΠΙΛΟΓΗ ΕΙΚΟΝΑΣ";

    if (imageLoaded) {
        $("#loadImage").hide();
        $("#removeImage").show();
        buttonTitle = "ΑΦΑΙΡΕΣΗ ΕΙΚΟΝΑΣ";
    } else {
        $("#loadImage").show();
        $("#removeImage").hide();
    }

    $("#bg_image").attr("title", buttonTitle);
}

$("#bgCheck").change(function () {
    bgCheck = $(this).is(":checked");
});

$("#bgColor").on("change", function () {
    if (bg_color != $(this).val()) {
        imageLoaded = 0;
        updateImageButtons();
    }
    bg_color = $(this).val();
});

$("#bgCheck").change();
$("#bgColor").change();

$("#bg_image").click(function () {
    if (imageLoaded) {
        imageLoaded = 0;
        updateImageButtons();
    } else {
        $("#formFile").click();
    }
});

$("#formFile").change(function (e) {
    let image = e.target.files[0];
    imageLoaded = 0;

    let isImage = image.name.match(/[.]png|gif|jpg|jpeg|jfif|pjpeg|pjp$/);

    if (image && isImage) {
        let reader = new FileReader();
        reader.readAsDataURL(image);

        reader.addEventListener("load", function () {
        imgData = reader.result;
        //console.log(imgData)
        try {
            bgImage = loadImage(imgData);
            imageLoaded = 1;
            if (!bgCheck) {
                $("#bgCheck").click();
            }
        } catch (err) {
            imageLoaded = 0;
        }
        updateImageButtons();
        });
    } else {
        updateImageButtons();
    }
});

$(".standard_buttons button").mousedown(function () {
    isActive = $(this).hasClass("active selected");
});

// -------- Smooth edges
$("#smooth").on("input change", function () {
    smooth_val = parseFloat($(this).val());
    if(!isSafari && !isMobile) {  // Blur fix for Safari 3/3
        buff.drawingContext.filter = `blur(${smooth_val}px)`;
    }
});

// -------- change Backround opacity (set to 0.3 in style.css)
$("#background_opacity").on("input change", function () {
    $('#background_canvas').css("opacity", $(this).val());
});

// -------- Graphic Tools controls (circle, square, text, pencil, etc)
$(".standard_buttons button").click(function () {
    $(".standard_buttons button")
        .removeClass("active selected")
        .attr("aria-pressed", "false");

    tool = "";
    if (isActive) {
        $(this).removeClass("active selected").attr("aria-pressed", "false");
    } else {
        $(this).addClass("active selected").attr("aria-pressed", "true");
        tool = $(this).attr("id");
    }

    fill_color = init_fill_color;

    if (tool == "eraser") {
        fill_color = bg_color;
    }

    if (visibleText) {
        hide_text();
    }
});

const confirmModal = document.getElementById("confirm");

confirmModal.addEventListener("shown.bs.modal", (event) => {
    $("#confirm_yes").focus();
});

confirmModal.addEventListener("hidden.bs.modal", (event) => {
    if (confirmation) {
        $("#alert").text("Το περιεχόμενο διαγράφηκε");
        cnv.background(bg_color);
        buff.clear();
        hide_text();
        redraw();
        current_undo++
        //first_load = 1;
        imageLoaded = 0;
        resize_canvas();

        if (FIX_IMAGE) {
            preload();
        }

        with (cnv) {
            clear();
            redraw();
        }
        confirmation = 0;
        updateImageButtons();
    }
});

$("#confirm button").click(function () {
    confirmation = $(this).data("confirm");
});

$("#clear").click(function () {
    $("#confirm").modal("show");
});

$("#save").click(function () {
    save_canvas();
});

$("#undo").click(function () {
    force_undo = 1;
    keyCode = 90;
    keyPressed();
});

$("#redo").click(function () {
    force_redo = 1;
    keyCode = 90;
    keyPressed();
});

function init_controls() {
    $("#pencil").click().attr("aria-pressed", "true");
    $("#color_samples_stroke .btn-info, #color_samples_fill .btn-warning")
        .click()
        .addClass("active")
        .attr("aria-pressed", "true");

    $("#stroke_weight button")
        .eq(1)
        .click()
        .addClass("active")
        .attr("aria-pressed", "true");
    $("#smooth").val(0);
    smooth_val = 0;

    if (!$("#fillCheck").is(":checked")) {
        $("#fillCheck").prop("checked", true);
    }
    if (!$("#strokeCheck").is(":checked")) {
        $("#strokeCheck").prop("checked", true);
    }

    if (!$("#bgCheck").is(":checked")) {
        $("#bgCheck").click();
    }

    $("#fillColor").val(fill_color);
    $("#strokeColor").val(stroke_color);
    $("#bgColor").val(bg_color);

    let undo_levels_info = (UNDO_LEVELS === 1) ? 'επίπεδο' : 'επίπεδα' 
    $('#undo_info').html(` &nbsp; [${UNDO_LEVELS} ${undo_levels_info}]`)
    update_undo_buttons()
}