let cnv
let W, H;
let offsetX, offsetY
let maxW
let global_scale3 = 1
let t = 0;
let first_load = 1;
let line_color = "#000";
let show_image = 0
let autoSolve = solved = 0 
let transparency = 40
let imageLoaded = 0;
let timeoutID = null
let startTime = endTime = 0
let size_division = 7
let psW, psH, itemsW, itemsH //piece size
let shuffle_grid = 0
let imgData = imgData3 = ""
let data = []
let bgImage = null
let image_width = 0;
let image_height = 0;
let image_aspect = 0;
const canvasAspectRatio = 940/628;
let zoom = 1;
let proximity = 5;
const MIN_ZOOM = 0.4;
const MAX_ZOOM = 2.0;
const MIN_PROXIMITY = proximity;
const MAX_PROXIMITY = proximity * 5;

// zoom functions
function applyZoom() {
    zoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, zoom));
    $('#zoom').val(zoom);
    zoom = parseFloat(zoom)
    $('.zoom-value').text(zoom.toFixed(1));
    randomized.scale(zoom);
    randomized.puzzle.proximity = calculateProximity();
    randomized.redraw();

    if(zoom != 1){
        $("#reset_zoom").removeClass('disabled')
    } else {
        $("#reset_zoom").addClass('disabled')
    }
}

$('#canvas_wrapper').on('wheel', function(e) {
  e.preventDefault();
  const delta = e.originalEvent.deltaY < 0 ? 0.2 : -0.2;
  zoom += delta;
  zoom = parseFloat(zoom.toFixed(2));
  applyZoom();
});

$('#zoom').on("input change", function () {
    zoom = $(this).val();
    applyZoom();
});

$('#reset_zoom').on("click", function () {
    zoom = 1;
    applyZoom();
});

function calculateProximity() {
  if (zoom >= 1) return MIN_PROXIMITY;
  const t = (1 - zoom) / (1 - MIN_ZOOM);
  let prox = MIN_PROXIMITY + t * (MAX_PROXIMITY - MIN_PROXIMITY)
  prox = Math.min(Math.min(psW, psH)-2, prox) 
  return Math.round(prox);
}

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

cnv_wrapper = document.getElementById("canvas_wrapper");

$('#alert_success').text(SUCCESS_MESSAGE)

function setup() {
    cnv = createCanvas(200, 200);
    drawingContext.filter = 'brightness(110%)'
    cnv.hide()
    fill(255)
}

function draw(){
    isDark = $("body").hasClass("dark-mode");

    //console.log(isDark, $('.konvajs-content').css('backgroundColor'))

    if(isDark) {
        background('#1f1f1f')
    }else{
        background(255)
    }
    
    tint(255, 255, 255, (transparency/100)*255)

    if(bgImage && bgImage != undefined){
        image(bgImage, 0, 0, itemsW*psW, imgH, 0, 0, bgImage.width, bgImage.height)
    }
    noLoop()
}

// -------- Image puzzle item's divisor
$("#size_division").val(size_division)
$("#size_division_label").text(size_division)

$("#size_division").on("input change", function () {
    size_division = $(this).val()

    pre_init_puz()

    $("#size_division_label").text(size_division)
});

// -------- transparency
$("#transparency").on("input change", function () {
    transparency = $(this).val()

    redraw()
    imgData = cnv.canvas.toDataURL("image/jpeg") 
    $('.konvajs-content').css({ backgroundImage: `url(${imgData})`,  backgroundRepeat: 'no-repeat', backgroundSize: `${cnv.width}px ${cnv.height}px` })
})

$("#show_image").change(function () {
    if (!imageLoaded){
        return false
    }

    show_image = $(this).is(":checked");

    if(show_image) {
        $("#transparency_wrapper").show()
        $("#transparency").change()
        $('.konvajs-content').css({ backgroundImage: `url(${imgData})`,  backgroundRepeat: 'no-repeat', backgroundSize: `${cnv.width}px ${cnv.height}px` })
    } else {
        $("#transparency_wrapper").hide()
        $('.konvajs-content').css({ backgroundImage: 'none'})
    }
})

// -------- Shuffle controls
$("#shuffle_but").click(function () {
    autoSolve = solved = 0

    shuffle_grid = !shuffle_grid

    try {
        if(shuffle_grid){
            randomized.shuffleGrid()
        } else {
            randomized.shuffle(0.7)
        }          
        randomized.redraw();
    } catch {}

    startTime = new Date().getTime()
});

$("#solve_but").click(function () {
    init_puz()
    setTimeout(function(){
        try {
            randomized.solve()
            // fix for centering puzzle on solving (must change the x,y position for each piece with the half position of first piece)
            newX = newY = 0;
            randomized.puzzle.pieces.forEach(piece => {
                if(newX == 0 && newY == 0){
                    newX = piece.metadata.targetPosition.x;
                    newY = piece.metadata.targetPosition.y;
                    // Get total width or heigh and remove the full width or height of all pieces and from that remove the half of first piece (it is 0 position) to get the offset for centering.
                    offsetX = ((W - (itemsW*newX))/2) - (newX/2);
                    offsetY = ((H - (itemsH*newY))/2) - (newY/2);
                }
                piece.translate(offsetX, offsetY);
            });
            // Draw pieces in new positions
            randomized.redraw()
            autoSolve = 1
        } catch {}
    }, 100)
});

$('body').click(function(){
    $('#alert_success').hide()
})

$("#bg_image").click(function (e) {
    $('#alert_success').hide()
    $("#formFile").val("").click();
});

let randomized

function init_puz(){
    $('#zoom').val(1);
    let mi = new Image();
    mi.src = imgData3

    mi.onload = () => {

        randomized = new headbreaker.Canvas('my-canvas', {
            width: W, 
            height: H,
            pieceSize: {x: psW, y: psH},
            proximity: proximity,
            borderFill: 0, 
            strokeWidth: 1,
            strokeColor: line_color,
            lineSoftness: 0.12, 
            image: mi,
            preventOffstageDrag: true,
            outline: new headbreaker.outline.Rounded(),
        });

        randomized.adjustImagesToPuzzleWidth();
        
        randomized.autogenerate({
            horizontalPiecesCount: itemsW,
            verticalPiecesCount: itemsH,
            insertsGenerator: headbreaker.generators.flipflop
        });

        if(!shuffle_grid) {
            randomized.shuffle(0.7)
            first_load = 0
        } else {
            randomized.shuffleGrid();
        }

        randomized.registerKeyboardGestures();
        randomized.draw();
        
        try{
           registerButtons('keyboard', randomized); 
        }catch(err){ }
        
        randomized.attachSolvedValidator();
        startTime = new Date().getTime()
        autoSolve = 0

        randomized.onValid(function(){
            if(autoSolve || solved){
                return true
            }

            endTime = new Date().getTime();
            secs = (endTime - startTime)/1000
            hours = Math.floor(secs/3600)
            secs = secs - hours * 3600
            hours = (hours < 10) ? '0' + hours : hours
            mins = Math.floor(secs/60)
            secs = secs - mins * 60
            mins = (mins < 10) ? '0' + mins  : mins 
            secs = Math.round(secs%60)
            secs = (secs < 10) ? '0' + secs  : secs
            
            $('#alert_success').text( SUCCESS_MESSAGE + `  Χρόνος: ${hours}:${mins}:${secs}`)

            solved = 1

            setTimeout(function(){
                let alert_left = $('#main').offset().left + $('#main').width()/4
                $('#alert_success').css({ width: $('#main').width()/2 + 'px', left: alert_left + 'px', top: $('#main').height()/2 + 'px' }).fadeIn();
            }, 500)
        })

        setTimeout(function(){
            if (show_image) {
                $('.konvajs-content').css({
                    backgroundImage: `url(${imgData})`,
                    backgroundRepeat: 'no-repeat',
                    backgroundSize: `${cnv.width}px ${cnv.height}px`
                })
            }
            applyZoom();
        }, 50)
    }
}

function pre_init_puz() {

    if(!imageLoaded){
        return false;
    }

    solved = 0

    $('#my-canvas').remove()

    maxH = $('#canvas_wrapper').height();
    W = $('#canvas_wrapper').width();

    if(timeoutID != undefined){
        clearTimeout(timeoutID)
    }

    timeoutID  = setTimeout(function(){

        // Calculate scale to fit image INSIDE the target box
        scale = min(
            W / image_width,
            maxH / image_height
        )
        imgW = int(image_width * scale)
        imgH = int(image_height * scale)

        H = maxH

        //ps = Math.min(imgW, imgH)/size_division
        psW = imgW/size_division
        psH = imgH/size_division

        itemsW = size_division
        itemsH = size_division

        resizeCanvas(W, H)

        bgImage = loadImage(imgData3, function(img2){
            bgImage = img2

            redraw()

            $('#my-canvas').remove()
            $('#canvas_wrapper').append('<div id="my-canvas" class="h-100"> </div>')
            
            if(first_load){
                $('#canvas_wrapper').append(cnv.canvas)

                $('#defaultCanvas0').click(function(){
                    $('#show_image').click()
                })
            }

            cnvLeft = $('#canvas_wrapper').width() - $('#defaultCanvas0').width()
            $('#defaultCanvas0').css({position: 'absolute', left: cnvLeft + 'px', top: '0px'})

            imgData = cnv.canvas.toDataURL("image/jpeg")

            init_puz()

            $('.inactive').removeClass('inactive')

        });
        
        if(first_load && imageLoaded){
            if(SHOW_IMAGE){
                $("#help_btn_wrapper").removeClass('d-none')
                $("#zoom_wrapper").removeClass('d-none')
            }
            if(SOLVE_BUTTON){
                $("#solve_btn_wrapper").removeClass('d-none')
            }
            $("#shuffle_btn_wrapper").removeClass('d-none')
            // $('#show_image').prop("checked", false).change()
            maxW = $("#inner_container").width() - $("#controls_wrapper").outerWidth();
            first_load = 0
        }

        maxW = $("#inner_container").width() - $("#controls_wrapper").outerWidth()

        $("#items_stats").text('('+ itemsW * itemsH + ' κομμάτια)')

    }, 500)
}

$('#canvas_wrapper').click(function(e){
    if ($(e.target).closest('.popover').length) {
        return; // if clicked inside popover do nothing
    }

    if (!imageLoaded) {
        $("#bg_image").click()
    }
})

$("#formFile").change(function (e) {
    let image = e.target.files[0];
    imageLoaded = 0;
    shuffle_grid = 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;
            imgData3 = imgData
            imageLoaded = 1

            let tmpImage = new Image();
            tmpImage.src = imgData3;
            tmpImage.onload = function () {
                // Get image size and aspect
                image_width = tmpImage.width;
                image_height = tmpImage.height;
                image_aspect = image_width/image_height;

                // Convert image to jpg if it is not
                if (image.type !== "image/jpeg") {
                    let canvas = document.createElement("canvas");
                    canvas.width = tmpImage.width;
                    canvas.height = tmpImage.height;

                    let ctx = canvas.getContext("2d");
                    // fill background with white color for transparency to become white
                    ctx.fillStyle = "#ffffff";
                    ctx.fillRect(0, 0, canvas.width, canvas.height);
                    ctx.drawImage(tmpImage, 0, 0);

                    // convert to JPG
                    imgData3 = canvas.toDataURL("image/jpeg", 1);
                    imgData = imgData3;
                }
            }
            pre_init_puz();
        });
    } 
});

function init_controls() {
    $('#show_image').prop("checked", false);
    $("#transparency_wrapper").hide();
    $('#transparency').val(transparency);
    $('#zoom').val(zoom);
}