/**
 * Created by rockyl on 2018/11/5.
 *
 * 渲染上下文
 */

import {updateScaleMode} from "./InteractContext";
import Bounds from "../../support/Bounds";

let _canvas, context, width, height;

let scaleX, scaleY, rotation = 0;

let _designWidth, _designHeight, _scaleMode, _modifyCanvasSize;

let shortcutCanvas;

/**
 * 缩放模式
 *
 * SHOW_ALL: 全可见
 * FIXED_WIDTH: 宽度固定
 * FIXED_HEIGHT: 高度固定
 */
export const ScaleMode = {
	SHOW_ALL: 'showAll',
	FIXED_WIDTH: 'fixedWidth',
	FIXED_HEIGHT: 'fixedHeight',
};

/**
 * 装配上下文
 * @param options
 */
export function setupContext(options: any = {}) {
	const {canvas, designWidth, designHeight, scaleMode = ScaleMode.SHOW_ALL, modifyCanvasSize = false} = options;

	_designWidth = designWidth;
	_designHeight = designHeight;
	_scaleMode = scaleMode;
	_modifyCanvasSize = modifyCanvasSize;

	_canvas = canvas;
	context = canvas.getContext('2d');

	updateScaleModeSelf();
}

/**
 * 清空渲染上下文
 */
export function clear() {
	context.setTransform(1, 0, 0, 1, 0, 0);
	context.clearRect(0, 0, width, height);
}

/**
 * 获取渲染上下文
 */
export function getContext() {
	return context;
}

/**
 * 获取舞台尺寸
 */
export function getStageSize() {
	return {
		width,
		height,
	}
}

/**
 * 获取舞台缩放
 */
export function getStageScale() {
	return {
		x: scaleX,
		y: scaleY,
	}
}

/**
 * 获取舞台中心
 */
export function getStageCenter() {
	return {
		x: width / 2,
		y: height / 2,
	}
}

/**
 * 创建canvas
 */
export function createCanvas() {
	return document.createElement('canvas');
}

interface ShortcutParams {
	imgType: string;
	zoomToDom?: boolean;
	quality?: number;
	bounds?: Bounds;
}

/**
 * 截图
 * @param type 目标格式 0:Image, 1:DataURL
 * @param params
 */
export async function shortcut(type: number = 0, params: ShortcutParams) {
	let targetImg;

	if(params.bounds || params.zoomToDom){
		const dataUrl = _canvas.toDataURL('image/png');
		const img = await dataUrlToImage(dataUrl);
		targetImg = await shortcutWithSize(img, type, params.imgType, params.quality, params.bounds, params.zoomToDom ? scaleX : 1);
	}else{
		targetImg = _canvas.toDataURL(params.imgType, params.quality);
	}

	return targetImg;
}

function dataUrlToImage(dataUrl) {
	return new Promise((resolve, reject) => {
		const image = new Image();
		image.onload = function () {
			resolve(image);
		};
		image.onerror = function (e) {
			reject(e);
		};
		image.src = dataUrl;
	})
}

async function shortcutWithSize(img, type, imgType, quality?, bounds?:Bounds, scale = 1) {
	if (!shortcutCanvas) {
		shortcutCanvas = createCanvas();
	}
	const sx = bounds ? bounds.x || 0 : 0;
	const sy = bounds ? bounds.y || 0 : 0;
	const sw = bounds ? (bounds.width ? Math.min(bounds.width, width) : width) : width;
	const sh = bounds ? (bounds.height ? Math.min(bounds.height, height) : height) : height;
	const dw = sw * scale;
	const dh = sh * scale;
	shortcutCanvas.width = dw;
	shortcutCanvas.height = dh;
	const context = shortcutCanvas.getContext('2d');
	context.drawImage(img, sx, sy, sw, sh, 0, 0, dw, dh);

	const dataUrl = shortcutCanvas.toDataURL('image/' + imgType, quality);
	switch (type) {
		case 0:
			return await dataUrlToImage(dataUrl);
		case 1:
			return dataUrl;
	}
}

/**
 * 更新缩放模式
 */
function updateScaleModeSelf() {
	let parent = _canvas.parentElement;
	let containerWidth = parent.clientWidth;
	let containerHeight = parent.clientHeight;

	const designWidth = _designWidth || containerWidth;
	const designHeight = _designHeight || containerHeight;

	scaleX = containerWidth / designWidth;
	scaleY = containerHeight / designHeight;
	switch (_scaleMode) {
		case ScaleMode.SHOW_ALL:
			width = designWidth;
			height = designHeight;
			break;
		case ScaleMode.FIXED_WIDTH:
			width = designWidth;
			if(_modifyCanvasSize){
				height = designHeight;
			}else{
				height = containerHeight / scaleX;
			}
			scaleY = scaleX;
			break;
		case ScaleMode.FIXED_HEIGHT:
			if(_modifyCanvasSize){
				width = designWidth;
			}else{
				width = containerWidth / scaleY;
			}
			height = designHeight;
			scaleX = scaleY;
			break;
	}

	updateScaleMode(scaleX, scaleY, rotation);

	let styleWidth = _modifyCanvasSize ? designWidth * scaleX : containerWidth;
	let styleHeight = _modifyCanvasSize ? designHeight * scaleY : containerHeight;

	_canvas.width = width;
	_canvas.height = height;
	_canvas.style.display = 'block';
	_canvas.style.width = styleWidth + 'px';
	_canvas.style.height = styleHeight + 'px';
}
