/**
 * 兼容高分辨率屏幕高像素比的情况
 * 
 * @param {*} context 
 */
function getPixelRatio(context) {
    let backingStore = context.backingStorePixelRatio ||
        context.webkitBackingStorePixelRatio ||
        context.mozBackingStorePixelRatio ||
        context.msBackingStorePixelRatio ||
        context.oBackingStorePixelRatio ||
        context.backingStorePixelRatio || 1
    return (window.devicePixelRatio || 1) / backingStore
}

/**
 * 使用指定画布，按照云阅卷拼接规则，将已加载好的图片拼接成新的图片对象
 * 
 * @param {canvas} canvas 
 * @param {array} images 
 * @param {array} config 
 * @param {function} onSuccess 
 * @param {function} onError 
 */
function mergeImages(canvas, images, config, onSuccess, onError) {
    if (config == undefined || config.length == 0) {
        //不指定拼接配置时，默认按顺序显示所有图片
        config = []
        for (let i = 0; i < images.length; i++) {
            config.push({
                i: i + 1,
                x: 0,
                y: 0,
                w: 0,
                h: 0
            })
        }
    }
    let maxWidth = 0
    let totalHeight = 0
    for (let i = 0; i < config.length; i++) {
        //计算最大宽度与合计高度
        if (config[i].w <= 0) {
            config[i].w = images[config[i].i - 1].width
        }
        if (config[i].h <= 0) {
            config[i].h = images[config[i].i - 1].height
        }
        maxWidth = Math.max(maxWidth, config[i].w)
        totalHeight += config[i].h
    }
    let context = canvas.getContext("2d")
    //获取设备像素比
    //暂时只用原始尺寸，避免转换图片过大导致性能问题
    //let ratio = getPixelRatio(context)
    let ratio = 1
    //设置画布大小
    canvas.width = maxWidth * ratio
    canvas.height = totalHeight * ratio
    context.clearRect(0, 0, canvas.width, canvas.height)
    context.fillStyle = "white";
    context.fillRect(0, 0, canvas.width, canvas.height);
    //绘画到画布
    //高度位置与图片配置对应关系
    let array = []
    let top = 0
    let height = 0
    for (let i = 0; i < config.length; i++) {
        context.drawImage(images[config[i].i - 1], config[i].x, config[i].y, config[i].w, config[i].h, 0, height, config[i].w * ratio, config[i].h * ratio)
        height += config[i].h * ratio
        top += config[i].h
        array.push({
            offsetY: top,
            config: config[i]
        })
    }
    let image = new Image()
    if (onSuccess) {
        image.onload = function() {
            onSuccess(image)
        }
    }
    if (onError) {
        image.onerror = function() {
            onError('image merge error')
        }
    }
    image.config = array
    // image.origin = {
    //     width: maxWidth,
    //     height: totalHeight
    // }
    image.src = canvas.toDataURL()
    return image
}

/**
 * 针对云阅卷场景多图片处理工具
 * 1. 支持指定服务器地址与是否强制刷新
 * 2. 支持按云阅卷规则筛选实际需要加载的图片
 * 3. 支持动态使用画布，按云阅卷规则垂直拼接出新的图片
 * 
 * @param {*} option 
 */
function ImageLoader(option) {
    option = option || {}
    this.server = option.server || ''
    this.flush = option.flush === true
}

ImageLoader.prototype.load = function(urls, config, onSuccess, onError) {
    let promises = []
    let images = []
    for (let i = 0; i < urls.length; i++) {
        let url = this.server + urls[i] + (this.flush ? ('?' + new Date().getTime()) : '')
        let image = new Image()
        images.push(image)
        promises.push(new Promise((resolve, reject) => {
            if (this.contain(i + 1, config)) {
                image.onload = function() {
                    resolve()
                }
                image.onerror = function() {
                    reject(url + ' load error')
                }
                image.crossOrigin = ''
                image.src = url
            } else {
                resolve()
            }
        }))
    }

    Promise.all(promises).then(() => {
        onSuccess ? onSuccess(images) : (function() {})
    }).catch(error => {
        onError ? onError(error) : (function() {})
    })
}

/**
 * 判断指定序号的图片是否在拼接规则中存在，默认返回true
 * 
 * @param {number} number 
 * @param {array} config 
 */
ImageLoader.prototype.contain = function(number, config) {
    if (config != undefined && config.length > 0) {
        let find = false
        for (let i = 0; i < config.length; i++) {
            if (config[i].i == number) {
                find = true
                break
            }
        }
        return find
    } else {
        return true
    }
}

ImageLoader.prototype.merge = function(urls, config, onSuccess, onError) {
    if (this.canvas == undefined) {
        this.canvas = document.createElement('canvas')
    }
    this.canvas.style = 'display:none'

    let canvas = this.canvas
    this.load(urls, config, function(images) {
        mergeImages(canvas, images, config, onSuccess, onError)
    }, onError)
}

/**
 * 针对画布的辅助工具类
 * 1. 灵活调整大小与视网膜屏幕下的高清显示
 * 2. 按照云阅卷的图片拼接规则绘制图片内容
 * 
 * @param {} option 
 */
function EasyCanvas(option) {
    this.canvas = option.canvas
    this.context = this.canvas.getContext("2d")
    this.ratio = getPixelRatio()

    this.originSize = {
        width: 0,
        height: 0
    }
    this.styleSize = {
        width: 0,
        height: 0
    }
    this.boxSize = {}
    this.changeBoxSize(option.boxWidth, this.boxHeight)

    this.fontConfig = {
        name: option.fontName || 'Arial',
        size: option.fontSize || 60,
        color: option.fontColor || 'red'
    }
    this.lineConfig = {
        width: option.lineWidth || 3,
        color: option.lineColor || 'red'
    }

    this.onClick = option.onClick || (function() {})

    let self = this
    this.canvas.onclick = function(event) {
        if (self.originSize.width > 0 && self.originSize.height > 0) {
            self.onClick({
                left: event.offsetX,
                top: event.offsetY
            })
        }
    }
}

EasyCanvas.prototype.changeBoxSize = function(width, height) {
    if (width != undefined) {
        this.boxSize.width = width
        this.boxSize.height = undefined
    } else if (height != undefined) {
        this.boxSize.height = height
        this.boxSize.width = undefined
    }
}

EasyCanvas.prototype.clear = function() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.heigth)
}

EasyCanvas.prototype.reset = function(width, height) {
    this.originSize.width = Math.max((width || 0), 0)
    this.originSize.height = Math.max((height || 0), 0)
    this.styleSize.width = this.originSize.width
    this.styleSize.height = this.originSize.height

    if (this.styleSize.width > 0 && this.styleSize.height > 0) {
        if (this.boxSize.width != undefined) {
            this.styleSize.width = Math.min(this.originSize.width, this.boxSize.width)
            this.styleSize.height = this.styleSize.width * this.originSize.height / this.originSize.width
        } else if (this.boxSize.height != undefined) {
            this.styleSize.height = Math.min(this.originSize.height, this.boxSize.height)
            this.styleSize.width = this.styleSize.height * this.originSize.width / this.originSize.height
        }
    }

    this.canvas.width = this.styleSize.width * this.ratio
    this.canvas.height = this.styleSize.height * this.ratio
    this.canvas.style.width = this.styleSize.width + 'px'
    this.canvas.style.height = this.styleSize.height + 'px'

    this.clear()
}

EasyCanvas.prototype.drawImage = function(image, scale) {
    this.drawImages([image], undefined, scale)
}

EasyCanvas.prototype.drawImages = function(images, config, scale) {
    scale = scale || 1.0
    if (config == undefined || config.length == 0) {
        //不指定拼接配置时，默认按顺序显示所有图片
        config = []
        for (let i = 0; i < images.length; i++) {
            config.push({
                i: i + 1,
                x: 0,
                y: 0,
                w: 0,
                h: 0
            })
        }
    }
    let maxWidth = 0;
    let totalHeight = 0;
    for (let i = 0; i < config.length; i++) {
        //计算最大宽度与合计高度
        if (config[i].w <= 0) {
            config[i].w = images[config[i].i - 1].width;
        }
        if (config[i].h <= 0) {
            config[i].h = images[config[i].i - 1].height;
        }
        maxWidth = Math.max(maxWidth, config[i].w * scale);
        totalHeight += config[i].h * scale;
    }
    if (maxWidth > 0 && totalHeight > 0) {
        //设置画布大小
        this.reset(maxWidth, totalHeight)
        //绘画到画布
        scale = scale * this.styleSize.width / this.originSize.width
        let height = 0;
        for (let i = 0; i < config.length; i++) {
            this.context.drawImage(images[config[i].i - 1], config[i].x, config[i].y, config[i].w, config[i].h, 0, height, config[i].w * scale * this.ratio, config[i].h * scale * this.ratio);
            height += (config[i].h * scale * this.ratio);
        }
    } else {
        this.reset()
    }
}

EasyCanvas.prototype.drawText = function(text, left, top) {
    this.context.font = this.fontConfig.size * this.ratio + 'px ' + this.fontConfig.name
    this.context.fillStyle = this.fontConfig.color
    this.context.fillText(text, left * this.ratio, top * this.ratio)
}

EasyCanvas.prototype.drawShape = function(trace) {
    if (trace && trace.length > 0) {
        this.context.lineWidth = this.lineConfig.width
        this.context.strokeStyle = this.lineConfig.color

        this.context.beginPath()
        this.context.moveTo(trace[0].x, trace[0].y)
        for (let i = 1; i < trace.length; i++) {
            this.context.lineTo(trace[i].x, trace[i].y)
            this.context.stroke()
        }
        this.context.closePath()
    }
}