package com.isidroid.rendering.ext

import com.isidroid.rendering.constant.PrintSize
import com.isidroid.rendering.model.PrintCanvas

internal fun calculateScale(
    @PrintSize printSize: Int,
    canvasSize: PrintCanvas,
    settingsScale: Float,
    bitmapWidth: Int,
    bitmapHeight: Int
): Float {
    val calculatedScale = when (printSize) {
        PrintSize.PAPER_ORIGINAL_PAGE -> settingsScale
        PrintSize.FILL_PAGE -> fillPage(canvasSize, bitmapWidth, bitmapHeight)
        PrintSize.FIT_TO_PAPER -> fitToPaper(canvasSize, bitmapWidth, bitmapHeight)
        PrintSize.FIT_TO_PRINTABLE_AREA -> fitToPrintableArea(canvasSize, bitmapWidth, bitmapHeight)
        else -> 1f
    }
    return calculatedScale
}

private fun fillPage(canvasSize: PrintCanvas, bitmapWidth: Int, bitmapHeight: Int): Float {
    val isVerticalPicture = bitmapHeight > bitmapWidth
    val isPortraitOrientation = canvasSize.width > canvasSize.height

    val byWidth = (isVerticalPicture && isPortraitOrientation) || (!isVerticalPicture && isPortraitOrientation)

    return if (byWidth) canvasSize.width / bitmapWidth else canvasSize.height / bitmapHeight
}

private fun fitToPaper(canvasSize: PrintCanvas, bitmapWidth: Int, bitmapHeight: Int): Float {
    return calculateScale(canvasSize.width, canvasSize.height, bitmapWidth, bitmapHeight)
}

private fun fitToPrintableArea(canvasSize: PrintCanvas, bitmapWidth: Int, bitmapHeight: Int): Float {
    val width = canvasSize.width - canvasSize.marginLeft - canvasSize.marginRight
    val height = canvasSize.height - canvasSize.marginTop - canvasSize.marginBottom

    return calculateScale(width, height, bitmapWidth, bitmapHeight)
}

private fun calculateScale(containerWidth: Float, containerHeight: Float, bitmapWidth: Int, bitmapHeight: Int): Float {
    val a1 = check(containerWidth, containerHeight, bitmapWidth.toFloat(), bitmapHeight.toFloat())
    val a2 = check(containerHeight, containerWidth, bitmapHeight.toFloat(), bitmapWidth.toFloat())
    return (a1 ?: a2) ?: 1f
}

private fun check(cWidth: Float, cHeight: Float, width: Float, height: Float): Float? {
    val factor = cWidth / width
    val check = height * factor

    return if (check <= cHeight) factor else null
}