class BlueToothPrint {

    /** 打印初始参数 */
    p_width; // 打印纸张宽度
    p_height; // 打印纸张高度
    p_initX; // 打印纸张起点X坐标
    p_initY; // 打印纸张起点Y坐标
    p_style; // 打印纸样式 0-连续纸 1-间隔纸

    /** 打印状态 */
    cur_x; // 当前打印横向坐标
    cur_y; // 当前打印纵向坐标

    /** 表格 */
    table_width; // 表格宽度
    cell_width; // 单元格之间间隙-宽度
    cell_height; // 单元格之间间隙-高度
    line_text_spacing; // 单元格内线与内容的间距

    /** 功能 */
    BerlinWall; // 柏林墙

    /** 任务列表 */
    printStack;
    mapArrayList;
    mapParamTemplate;
    contentArrayList;

    /** 构造函数 */
    constructor(w, h, x, y,s) {
        // 初始化页面大小
        this.p_width = w;
        this.p_height = h;
        // 初始化打印起点X,Y
        this.p_initX = x;
        this.p_initY = y;
        // 初始化打印纸张样式
        this.p_style = s;
        // 初始化当前打印坐标X,Y
        this.cur_x = x;
        this.cur_y = y;
        // 初始化JSON参数
        this.mapArrayList = [];
        this.contentArrayList = [];
        this.createEmptyMapTemplate();
        // 初始化画布
        this.createCanvasElement()
        // 功能
        this.BerlinWall = 0;
    }

    init(w,h,x,y,s) {
        // 初始化页面大小
        this.p_width = w;
        this.p_height = h;
        // 初始化打印起点X,Y
        this.p_initX = x;
        this.p_initY = y;
        // 初始化打印纸张样式
        this.p_style = s;
        // 初始化当前打印坐标X,Y
        this.cur_x = x;
        this.cur_y = y;
        // 初始化JSON参数
        this.mapArrayList = [];
        this.contentArrayList = [];
        this.createEmptyMapTemplate();
        // 清空画布
        this.clearCanvas();
        // 功能
        this.BerlinWall = 0;
    }

    createEmptyMapTemplate() {
        this.mapParamTemplate = {
            width: this.p_width,
            height: this.p_height,
            style: this.p_style,
            content: []
        };
    }

    getPageHeight() {return this.cur_y;}

    /**
     * 打印
     */
    print() {
        this.putMapToArrayList();

        let param = {};
        let obj = $lj.getStorage("blueprint");
        console.log("obj ==>" + JSON.stringify(obj));
        if (!!obj && JSON.stringify(obj) != "{}") {
            param.address = obj.address;
        }
        param.print = this.mapArrayList;
        console.log("param ==>" + JSON.stringify(param));
        $lj.blueToothPrint_text(param,null);
    }

    drawText(isNextX,isNextY,fontType,fontSize,offset_x,offset_y,text) {
        // 判断是否有换行标志
        let height = getTextMaxHeight(text,fontType,fontSize);
        let textWidth = getTextWidth(text,fontType,fontSize);

        // if(this.cur_x + textWidth > this.BerlinWall) {

        // }

        if(text.indexOf("\r\n") >= 0) {
            let arr = text.split("\r\n");
            for(let i = 0;i < arr.length;i++) {
                this.drawText(isNextX,isNextY,fontType,fontSize,offset_x,offset_y + i * (height+6),arr[i]);
            }
        } else {
            var map = {};
            var map2 = {};
            map.method = "addText";
            map2.text_x = this.cur_x + offset_x;
            map2.text_y = this.cur_y + offset_y;
            map2.text = text;
            map2.fontSize = fontSize;
            map2.fontType = fontType;
            map.value = map2;
            console.log("drawText>>>>>>>>>>>>>>>>",JSON.stringify(map2))

            // 打印机光标是从上面开始，canvas光标是从下面开始
            if(this._preview != null) {
                this._preview.font = b(fontType,fontSize);
                this._preview.fillText(map2.text,map2.text_x,map2.text_y);
            }

            if (isNextX) this.cur_x += ( offset_x + textWidth);
            if (isNextY) this.cur_y += ( offset_y + height + 6);
            this.contentArrayList.push(map);
        }
    }

    drawPoText(isNextX,isNextY,fontType,fontSize,offset_x,offset_y,text) {
        let height = getTextMaxHeight(text,fontType,fontSize);
        let textWidth = getTextWidth(text,fontType,fontSize);

        if(text.indexOf("\r\n") >= 0) {
            let arr = text.split("\r\n");
            for(let i = 0;i < arr.length;i++) {
                this.drawText(isNextX,isNextY,fontType,fontSize,offset_x,offset_y + i * (height+6),arr[i]);
            }
        } else {
            var map = {};
            var map2 = {};
            map.method = "addText";
            map2.text_x = this.cur_x + offset_x - textWidth;
            map2.text_y = this.cur_y + offset_y;
            map2.text = text;
            map2.fontSize = fontSize;
            map2.fontType = fontType;
            map.value = map2;
            console.log("drawPoText>>>>>>>>>>>>>>>>",JSON.stringify(map2))

            // 打印机光标是从上面开始，canvas光标是从下面开始
            if(this._preview != null) {
                this._preview.font = b(fontType,fontSize);
                this._preview.fillText(map2.text,map2.text_x,map2.text_y);
            }

            if (isNextX) this.cur_x += ( offset_x);
            if (isNextY) this.cur_y += ( offset_y + height + 6);
            this.contentArrayList.push(map);
        }
    }

    /** 打印线条 */
    drawLine(isNextX,isNextY, lineWidth, start_x, start_y, end_x, end_y) {
        var map = {};
        var map2 = {};
        map.method = "addLine";
        map2.lineWidth = lineWidth;
        map2.start_x = start_x;
        map2.start_y = start_y;
        map2.end_x = end_x;
        map2.end_y = end_y;
        map.value = map2;
        console.log("drawLine>>>>>>>>>>>>>>>>",JSON.stringify(map2))

        // 设置预览画布效果
        if(this._preview != null) {
            this._preview.lineWidth = map2.lineWidth;
            this._preview.beginPath();
            this._preview.moveTo(map2.start_x, map2.start_y);
            this._preview.lineTo(map2.end_x, map2.end_y);
            this._preview.stroke();
        }

        if (isNextY) this.cur_y = end_y;
        if (isNextX) this.cur_x = end_x;
        this.contentArrayList.push(map);
    }

    /** 打印矩形 */
    drawBox(isNextX,isNextY, lineWidth, offset_x,offset_y,width, height) {
        var map = {};
        var map2 = {};
        map.method = "addBox";
        map2.lineWidth = lineWidth;
        map2.top_left_x = this.cur_x + offset_x;
        map2.top_left_y = this.cur_y + offset_y;
        map2.bottom_right_x = this.cur_x + offset_x + width;
        map2.bottom_right_y = this.cur_y + offset_y + height;
        map.value = map2;
        console.log("drawBox>>>>>>>>>>>>>>>>",JSON.stringify(map2))

        // 设置预览画布效果
        if(this._preview != null) {
            this._preview.lineWidth = map2.lineWidth;
            this._preview.strokeRect(map2.top_left_x,map2.top_left_y,map2.bottom_right_x - map2.top_left_x,map2.bottom_right_y - map2.top_left_y);
        }

        if (isNextY) this.cur_y += ( height + offset_y);
        if (isNextX) this.cur_x += ( width + offset_x);
        this.contentArrayList.push(map);
    }

    /** 打印图像 */
    drawGraphic(isNextX,isNextY, offset_x, offset_y, width, height, img) {
        var map = {};
        var map2 = {};
        map.method = "addEGraphics";
        map2.start_x = this.cur_x + offset_x;
        map2.start_y = this.cur_y + offset_y;
        map2.bmp_size_x = width;
        map2.bmp_size_y = height;
        map2.bmp = imageToBmp(img,width,height);
        map.value = map2;
        console.log("drawGraphic>>>>>>>>>>>>>>>>",JSON.stringify(map2))

        // 设置预览画布效果
        if(this._preview != null && img != null) {
            var image = new Image();
            image.src = imageToBase64(img,width,height);
            var self = this;
            image.onload=function(){
                self._preview.drawImage(image,map2.start_x,map2.start_y,map2.bmp_size_x,map2.bmp_size_y);
            }
        }

        if (isNextY)this.cur_y += (offset_y + height);
        if (isNextX)this.cur_x += (offset_x + width);
        this.contentArrayList.push(map);
    }

    /** 生成二维码 */
    drawQrBarcode(isNextX,isNextY, offset_x, offset_y, width,height, text,img){      
        var map = {};
        var map2 = {};
        map.method = "addBQrcode";
        map2.start_x = this.cur_x + offset_x;
        map2.start_y = this.cur_y + offset_y;
        map2.u = width / 21;
        map2.text = text;
        map.value = map2;
        console.log("drawQrBarcode>>>>>>>>>>>>>>>>",JSON.stringify(map2)) 

        // image主要用来在canvas上生成二维码
        if(img == null) {
            var image = new Image();
            image.src = '../../../../assets/image/default.png';
            image.width = width;
            image.height = width;
            var self = this;
            image.onload=function(){
                self._preview.drawImage(image,map2.start_x,map2.start_y,width,width);
            }
        }

        this.drawText(false,true,0,0,offset_x,offset_y + width + 6,text);

        // if (isNextY)this.cur_y += (offset_y + width);
        if (isNextX) this.cur_x += (offset_x + width);
        this.contentArrayList.push(map);
    }

    /** 打印多行文本,自动换行 */
    drawTextBox(isNextX,isNextY, fontType,fontSize,offset_x,offset_y,width, height, text) {
        console.log("textbox>>>",offset_x,offset_y,width,height,this.cur_x,this.cur_y,fontType,fontSize)
        var lineWidth = 0;
        var lastSubStrIndex = 0;
        var initX = offset_x;
        var initY = offset_y;

        // 记录cur_y,cur_x位置
        var now_y = this.cur_y;
        var now_x = this.cur_x;

        // 判断宽度是否超过柏林墙
        if(this.BerlinWall > 0 && this.cur_x + width > this.BerlinWall) {
            this.drawTextBox(isNextX,isNextY, fontType,fontSize,offset_x,offset_y,this.BerlinWall - this.cur_x, height, text);
            return;
        }

        var bytes = a(fontType,fontSize);
        
        let i = 0;
        let newStr = "";
        for (; i < text.length; i++) {
            if(isChinese(text[i])) {
                lineWidth += bytes;
            }else{
                lineWidth += (bytes >> 1)
            }
            if (lineWidth > width) {
                newStr = text.substring(lastSubStrIndex, i);
                this.drawText(false,true,fontType,fontSize,initX,initY,newStr);
                lineWidth = 0;
                lastSubStrIndex = i;
            }
        }

        if (i == text.length) {
            newStr = text.substring(lastSubStrIndex, i);
            this.drawText(false,false,fontType,fontSize,initX,initY,newStr);
        }

        this.cur_y = now_y;
        this.cur_x = now_x;

        if(height == null || height == 0) {
            if(text.length == 0) text = " ";
            height = (bytes + 6) * getTextLineCount(text,fontType,fontSize,width);
        }

        if (isNextY) this.cur_y += (offset_y + height);
        if (isNextX) this.cur_x += (offset_x + width);
    }

    /**************************************************** 表格(属性仅用于表格) ****************************************************/

    rows;//表格行集合

    clearTableRow() {
        this.rows = [];
    }

    addTableRow(row) {
        if(this.rows == null) {
            this.rows = [];
        }
        this.rows.push(row);
    }

    addTableRowList(rowlist) {
        if(this.rows == null) {
            this.rows = [];
        }
        this.rows = this.rows.concat(rowlist);
    }

    mergeTable(mTable){
        this.rows = this.rows.concat(mTable.rows);
    }

    drawTable() {
        for(let i = 0;i < this.rows.length;i++) {
            let row = this.rows[i];

            for(let j = 0;j < row.cells.length;j++) {
                let cell = row.cells[j];

                if (cell.type == "barcode") {
                    this.drawQrBarcode(false,false,cell.start_x + cell.paddingLeft,cell.start_y + cell.paddingTop,cell.boxWidth,cell.boxHeight,cell.value,cell.img);
                }else {
                    this.drawTextBox(false,false,cell.fontType,cell.fontSize,cell.start_x + cell.paddingLeft,cell.start_y + cell.paddingTop,cell.boxWidth,cell.boxHeight,cell.value);
                    
                    cell.child && this.drawTextBox(false,false,cell.child.fontType,cell.child.fontSize,cell.start_x + cell.paddingLeft,cell.start_y + cell.paddingTop + cell.boxHeight,cell.child.boxWidth,cell.child.boxHeight,cell.child.value);
                }

                this.drawBox(true,false,1,cell.start_x,cell.start_y,cell.width,row.rowHeight);
            }

            this.clearOffsetX();
            this.addOffsetY(row.rowHeight);
        }

        this.clearTableRow();
    }
    
    /*****************************             打印类画布                       ***************************/
    
    /** canvas */
    _canvas;
    _preview; // 预览打印画布对象
    preview_fontSize;
    preview_fontStyle;

    createCanvasElement() {
        var canvas = document.createElement('canvas');
        this._canvas = canvas
        this._canvas.width = this.p_width;
        this._canvas.height = 400;
        this._canvas.className = 'canvas';
        this._canvas.id = 'canvas';
        this._canvas.style.background = "#FFFFFF";

        this.createCanvasContext();
    }

    createCanvasContext() {
        // 创建canvas
        var canvas = this._canvas;
        var ctx = canvas.getContext("2d");
        // 设置或返回在绘制文本时使用的当前文本基线
        ctx.textAlign = 'left';
        ctx.textBaseline = 'top';
        
        this._preview = ctx;
    }

    getCanvasElement() {
        return this._canvas;
    }

    clearCanvas() {
        this._preview.clearRect(0,0,this._canvas.width,this._canvas.height);
    }

    /*****************************             打印类工具                       ***************************/
    clearOffsetX() {this.cur_x = this.p_initX;}
    clearOffsetY() {this.cur_y = this.p_initY;}
    addOffsetX(distance) {this.cur_x += distance;}
    addOffsetY(distance) {this.cur_y += distance;}
    getOffsetY() {return this.cur_y;}
    getOffsetX() {return this.cur_x;}

    setBerlinWall(x) {
        // 柏林墙是冷战期间民主德国政府环绕西柏林边境修筑的全封闭的边防系统，以将其与联邦德国管辖的西柏林市分割开来;
        this.BerlinWall = x;
    }

    /**
     * 存放每一次打印内容
     *
     **/
    putMapToArrayList() {
        if(this.contentArrayList.length <= 0) return;
        // 设置纸张高度为0,则自适应高度
        if(this.p_height <= 0) this.mapParamTemplate.height = this.getPageHeight();

        var cloneMap = JSON.parse(JSON.stringify(this.mapParamTemplate));
        var cloneList = JSON.parse(JSON.stringify(this.contentArrayList));
        cloneMap.content = cloneList;
        this.mapArrayList.push(cloneMap);
        // 初始化属性
        this.contentArrayList = [];
        this.createEmptyMapTemplate();
        this.clearOffsetX();
        this.clearOffsetY();
    }
    
}

/** 表格
 * cell：单元格 属性：padding,fontType,fontSize,align,boxwidth,boxheight,text
 * row：行
 */
export class tableRow {
    cells;
    rowHeight;

    /** 构造函数 */
    constructor(height) {
        this.cells = []
        this.rowHeight = height;
    }

    addTableCell(cell) {
        this.cells.push(cell);

        // 添加一次内容获取当前行内容的最大高度
        this.setMaxRowHeight(cell.height);
    }

    setMaxRowHeight(height) {
        this.rowHeight = Math.max(this.rowHeight,height);
    }
}

export class tableCell {
    // 内容参数
    type;
    value;
    fontType;
    fontSize;

    // 方位参数
    start_x;
    start_y;

    // 单元格参数
    boxWidth;
    boxHeight;
    height;
    width;
    paddingTop;
    paddingRight;
    paddingBottom;
    paddingLeft;

    // 
    img;

    //
    child;

    setPadding(padding) {
        this.paddingTop = this.paddingRight = this.paddingBottom = this.paddingLeft = padding;
    }

    setPaddingTop (padding) {
        this.paddingTop = padding;
    }

    setPaddingRight (padding) {
        this.paddingRight = padding;
    }

    setPaddingBottom (padding) {
        this.paddingBottom = padding;
    }

    setPaddingLeft (padding) {
        this.paddingLeft = padding;
    }

    setImage(img) {
        this.img = img;
    }
    
    setOffsetX(distance) {this.start_x = distance;}
    setOffsetY(distance) {this.start_y = distance;}

    addChild(child) {
        this.child = child;
        this.height += this.child.boxHeight;
    }

    /** 构造函数 */
    constructor(type,text,width,height,fontType,fontSize) {
        this.type = type;
        this.value = text;
        this.start_x = 0;
        this.start_y = 0;
        this.boxWidth = width;
        this.boxHeight = height;
        this.fontType = fontType;
        this.fontSize = fontSize;

        // 设置padding
        this.setPadding(5);

        if(this.boxWidth == 0) {
            this.boxWidth = getTextWidth(text,fontType,fontSize);
        } else {
            // 手动计算宽度的过程会忽略padding存在,因此boxWidth 要减去两边padding保持左右一致
            this.boxWidth -= (this.paddingLeft + this.paddingRight);
        }

        if(type == "text") {
            let line = getTextLineCount(text,fontType,fontSize,this.boxWidth);
            let lineHeight = getTextMaxHeight(text,fontType,fontSize) * line;
            this.boxHeight = Math.max(height,lineHeight);
        }

        // 计算外边框的高度宽度
        this.calcurlateWidth();
        this.calcurlateHeight();
    }

    calcurlateBoxWidth() {
        this.boxWidth -= (this.paddingLeft + this.paddingRight);
    }

    calcurlateWidth() {
        this.width = this.paddingLeft + this.paddingRight + this.boxWidth;
    }

    calcurlateHeight() {
        this.height = this.paddingTop + this.paddingBottom + this.boxHeight;
    }
}


/**
 * 获取文本宽度
 *
 * 分辨率203dpi,1mm等于8点(8dot/mm),每行打印密度为 576 dots
 *
 * */
function getTextWidth(text,type,size) {
    let sum = 0;
    for(var i = 0;i < text.length;i++){
        sum += getCharWidth(text[i],type,size);
    }
    return sum;
}

/**
 * 获取单个文字大小
 * @param {String} type 
 * @param {number} type 
 * @param {number} size 
 * @returns 
 */
function getCharWidth(char,type,size) {
    let sum = 0;
    if(isChinese(char)) {
        sum += a(type,size);
    }else {
        sum += (a(type,size) >> 1);
    }
    return sum;
}

function getTextMaxHeight(text,type,size) {
    let height = 0;
    for(var i = 0;i < text.length;i++){
        height = Math.max(height,a(type,size));
    }

    return height;
}

/**
 * 测量文本行数
 *
 * 分辨率203dpi,1mm等于8点(8dot/mm),每行打印密度为 576 dots
 *
 * */
function getTextLineCount(text,type,size,width) {
    let sum = getTextWidth(text,type,size);
    return Math.ceil(sum / width);
}

/**
 * 判断是否中文字符
 * @param {String} param 
 * @returns 
 */
function isChinese(param) {
    var reg = new RegExp("[\\u4E00-\\u9FFF]+","g");
    return reg.test(param);
}

function imageToBmp(img,width,height) {
    var canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0, width, height);
    var dataURL = canvas.toDataURL("image/png");
    dataURL = dataURL.replace(/^data:image\/(png|jpg|jpeg);base64,/, "");
    return dataURL;
}

function imageToBase64(img,width,height) {
    var canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0, width, height);
    return canvas.toDataURL("image/png");
}

// 文字大小
var _FONTSIZE = {
    "00": 16,
    "10": 24,
    "70": 28,
    "553": 32,
    "243": 48,
    "43": 64
}

// 画布文字大小
var _CTXFONTSIZE = {
    "00": "16px Arial",
    "10": "24px Arial",
    "70": "28px Arial",
    "553": "32px Arial",
    "243": "48px Arial",
    "43": "64px Arial"
}

function a(fontType,fontSize) {
    return _FONTSIZE[`${fontType}${fontSize}`];
}

function b(fontType,fontSize) {
    return _CTXFONTSIZE[`${fontType}${fontSize}`]
}


export default BlueToothPrint;