import lwip from 'lwip';
import Packer from './packer';

const propArray = ['path', 'format', 'dimension', 'sizeMore', 'colorDepth', 'imageClass', 'size', 'time', 'time2'];
const dimensionRegex = /(\d+)x(\d+)/;

const type = (operand) => {
    return Object.prototype.toString.call(operand).slice(8, -1).toLowerCase();
};
const transparent = [0, 0, 0, 0];
const openImage = (filepath) => {
    return new Promise((resolve, reject) => {
        lwip.open(filepath, (err, image) => {
            err ? reject(err) : (image.filepath = filepath, resolve(image));
        });
    });
};

const createImage = (width, height, color = transparent) => {
    return new Promise((resolve, reject) => {
        lwip.create(width, height, color, (err, image) => {
            err ? reject(err) : resolve(image);
        });
    });
};

const appendImage = (batch, left, top, width, height, image) => {
    for (let x = 0; x < width; x++) {
        for (let y = 0; y < height; y++) {
            batch.setPixel(left + x, top + y, image.getPixel(x, y));
        }
    }
    return batch;
};

const writeImage = (image, filepath, format, params) => {
    return new Promise((resolve, reject) => {
        image.writeFile(filepath, format, params, (err, image) => {
            err ? reject(err) : resolve(image);
        });
    });
};

/**
 * merge images
 * @param  {Array} sourceImgPaths source image paths
 * @param  {String} mergedImgPath  dest image path
 * @param  {String} arrange        how to merge images: 'vertical'|'horizental'|'smart'
 * @param  {number} margin         margin between images
 * @return {Object}                promise
 */
const mergeImage = async (sourceImgPaths, mergedImgPath, arrange = 'smart', margin = 0) => {
    if (!sourceImgPaths || !sourceImgPaths.length) {
        return Promise.reject('invalid sourceImgPaths');
    }
    if (type(sourceImgPaths) !== 'array') {
        sourceImgPaths = [sourceImgPaths + ''];
    }
    let images = await Promise.all(sourceImgPaths.map((filepath) =>
        openImage(filepath)));
    let rects = images.map((image, index) => {
        let width = image.width();
        let height = image.height();
        return { width, height, image };
    });
    let pack = new Packer().pack(Packer.sort(rects, 'maxSide'));
    let mergedImage = await createImage(pack.width, pack.height);
    let batch = mergedImage.batch();
    rects.reduce((preBatch, { pack: { x, y }, width, height, image}) => {
        return appendImage(preBatch, x, y, width, height, image);
    }, batch);
    await writeImage(batch, mergedImgPath, 'png', {
        compression: 'high',
        interlaced: true,
        transparency: true
    });
    return rects.map(({ pack: { x, y }, width, height, image}) => {
        return { x, y, width, height, path: image.filepath };
    });
};

export { mergeImage };

@@ -60,154 +60,34 @@
 nst 
-propArray = %5B'path', 'format', 'dimension', 'sizeMore', 'colorDepth', 'imageClass', 'size', 'time', 'time2'%5D;%0Aconst dimensionRegex = /(%5Cd+)x(%5Cd+)/
+transparent = %5B0, 0, 0, 0%5D
 ;%0A%0Ac
@@ -199,41 +199,107 @@
 %0A%7D;%0A
-const transparent = %5B0, 0, 0, 0%5D;
+%0A/**%0A * open image%0A * @param  %7BString%7D filepath image path%0A * @return %7BObject%7D          promise%0A */
 %0Acon
@@ -518,24 +518,235 @@
     %7D);%0A%7D;%0A%0A
+/**%0A * create a new blank image%0A * @param  %7BNumber%7D width  width%0A * @param  %7BNumber%7D height height%0A * @param  %7BArray%7CObject%7CString%7D color  bg color, default to transparent%0A * @return %7BObject%7D        promise%0A */%0A
 const create
@@ -969,24 +969,362 @@
     %7D);%0A%7D;%0A%0A
+/**%0A * append source image to target image%0A * @param  %7BObject%7D batch  target image or target image's batch%0A * @param  %7BObject%7D image  source image%0A * @param  %7BNumber%7D left   x coordinate%0A * @param  %7BNumber%7D top    y coordinate%0A * @param  %7BNumber%7D width  width%0A * @param  %7BNumber%7D height height%0A * @return %7BObject%7D        target image%0A */%0A
 const append
@@ -1338,16 +1338,23 @@
  (batch,
+ image,
  left, t
@@ -1370,23 +1370,16 @@
 , height
-, image
 ) =%3E %7B%0A 
@@ -1565,16 +1565,268 @@
 ch;%0A%7D;%0A%0A
+/**%0A * save image to file%0A * @param  %7BObject%7D image    image%0A * @param  %7BString%7D filepath file path%0A * @param  %7BString%7D format   image format: png%7Cjpg%7Cgif%0A * @param  %7BObject%7D params   format-specific parameters%0A * @return %7BObject%7D          promise%0A */%0A
 const wr
@@ -3229,16 +3229,23 @@
 reBatch,
+ image,
  x, y, w
@@ -3256,23 +3256,16 @@
 , height
-, image
 );%0A    %7D

add comment and remove unused code for image operation lib