// ================================================================
//                           CHEditor 5
// ================================================================

var activeImage = null,
    browser = null,
    button,
    debug = false,
    destinationObject = null,
    divHeight = [],
    divWidth = [],
    divXPositions = [],
    divYPositions = [],
    dragDropDiv,
    eventDiff_x = 0,
    eventDiff_y = 0,
    fileTypeRe = /^image\/(png|jpeg|gif|webp)$/i,
    geckoOffsetX_marker = -3,
    geckoOffsetY_marker = -1,
    imageCompleted = 0,
    imageCompletedList = [],
    imageListWrapper,
    imageResizeInput,
    imageResizeWidth = 0,
    insertionMarker,
    inputFileName = 'file',
    modifyImages = [],
    moveTimer = -1,
    oEditor = null,
    offsetX_marker = -3,
    offsetY_marker = -3,
    readyToMove = false,
    showThumbnailSize = { width: 120, height: 90 },
    tmpLeft = 0,
    tmpTop = 0,
    uploadImagePath = '',
    uploadMaxNumber = 12,
    uploadScript,
    useWebGL = false,
    supportImageOrientation;

if (ArrayBuffer && !ArrayBuffer.prototype.slice) {
    ArrayBuffer.prototype.slice = function (start, end) {
        var len = this.byteLength;
        start || isFinite(start) && 0 < start && start < len || (start = 0);
        end || (isFinite(end && start < end && end < len) || (end = len - 1));
        return new DataView(this, start, end).buffer;
    };
}

function GLScale(options) {
    if (!(this instanceof GLScale)) {
        return new GLScale(options);
    }
    this.precompile(options);
    return this.scale.bind(this);
}

GLScale.prototype.precompile = function (options) {
    var ctxOptions, vertex, fragment, resolutionLocation, positionLocation;

    this.canvas = document.createElement('canvas');
    this.canvas.width = options.width;
    this.canvas.height = options.height;

    ctxOptions = {preserveDrawingBuffer: true};
    this.gl = this.canvas.getContext('webgl', ctxOptions) || this.canvas.getContext('experimental-webgl', ctxOptions);

    if (!this.gl) {
        throw new Error('Could not initialize webgl context');
    }

    vertex = GLScale.compileShader(this.gl, GLScale.Hermite.vertex, this.gl.VERTEX_SHADER);
    fragment = GLScale.compileShader(this.gl, GLScale.Hermite.fragment, this.gl.FRAGMENT_SHADER);

    this.program = GLScale.createProgram(this.gl, vertex, fragment);
    this.gl.useProgram(this.program);

    this.gl.bindTexture(this.gl.TEXTURE_2D, this.gl.createTexture());

    this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
    this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
    this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
    this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);

    resolutionLocation = this.gl.getUniformLocation(this.program, 'u_resolution');
    this.gl.uniform2f(resolutionLocation, options.width, options.height);

    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.gl.createBuffer());
    positionLocation = this.gl.getAttribLocation(this.program, 'a_position');
    this.gl.enableVertexAttribArray(positionLocation);
    this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, false, 0, 0);
};

GLScale.prototype.scale = function (image, cb) {
    var srcResolutionLocation;
    if (typeof image === 'string') {
        return this.loadImage(image, function (err, image) {
            if (!err) {
                return this.scale(image, cb);
            }
        });
    }

    this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, image);

    srcResolutionLocation = this.gl.getUniformLocation(this.program, 'u_srcResolution');
    this.gl.uniform2f(srcResolutionLocation, image.width, image.height);

    this.setRectangle(0, 0, image.width, image.height);
    this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
    this.gl.finish();

    if (cb) {
        cb(this.canvas);
    }
    return this;
};

GLScale.prototype.setRectangle = function (x, y, width, height) {
    var x1 = x,
        x2 = x + width,
        y1 = y,
        y2 = y + height;

    this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([
        x1, y1,
        x2, y1,
        x1, y2,
        x1, y2,
        x2, y1,
        x2, y2
    ]), this.gl.STATIC_DRAW);
};

GLScale.loadImage = function (url, cb) {
    var image = new Image();
    image.onload = cb.bind(this, null, image);
    image.onerror = cb.bind(this);
    image.src = url;
    return this;
};
GLScale.prototype.loadImage = GLScale.loadImage;

GLScale.toBlob = (function toBlob() {
    var CanvasPrototype = window.HTMLCanvasElement.prototype;

    if (CanvasPrototype.toBlob) {
        return CanvasPrototype.toBlob;
    }

    return function (callback, type, quality) {
        var binStr = atob(this.toDataURL(type, quality).split(',')[1]),
            len = binStr.length,
            arr = new Uint8Array(len), i = 0;

        for (; i < len; i++) {
            arr[i] = binStr.charCodeAt(i);
        }
        callback(new Blob([arr], {type: type || 'image/png'}));
    };
})();

GLScale.compileShader = function (gl, shaderSource, shaderType) {
    var shader = gl.createShader(shaderType);
    
    gl.shaderSource(shader, shaderSource);
    gl.compileShader(shader);
    
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        throw new Error('Could not compile shader: ' + gl.getShaderInfoLog(shader));
    }
    return shader;
};

GLScale.createProgram = function (gl, vertexShader, fragmentShader) {
    var program = gl.createProgram();

    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    
    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        throw new Error('Program failed to link: ' + gl.getProgramInfoLog (program));
    }
    return program;
};

function createInsertionMaker() {
    var wrapper = document.getElementById('insertionMarker'),
        topIco = new Image(),
        middleIco = new Image(),
        bottomIco = new Image();

    topIco.src = uploadImagePath + '/marker_top.gif';
    topIco.style.width = '6px';
    topIco.style.height = '1px';
    wrapper.appendChild(topIco);

    middleIco.src = uploadImagePath + '/marker_middle.gif';
    middleIco.style.height = '96px';
    middleIco.style.width = '6px';
    wrapper.appendChild(middleIco);

    bottomIco.src = uploadImagePath + '/marker_bottom.gif';
    bottomIco.style.width = '6px';
    bottomIco.style.height = '1px';
    wrapper.appendChild(bottomIco);
}

function popupClose() {
    oEditor.popupWinCancel();
}

function showContents() {
    var spacer = function (id) {
        var clear = document.createElement('div');
        clear.style.height = '0px';
        clear.style.width = '0px';
        clear.className = 'clear';
        clear.id = 'spacer' + id;
        return clear;
    },
    spacerNo = 1, i, imgBox, theImg, lastSpacer;

    for (i = 0; i < uploadMaxNumber; i++) {
        if (i > 0 && i % 4 === 0) {
            imageListWrapper.appendChild(spacer(spacerNo++));
        }

        imgBox = document.createElement('div');
        imgBox.id = 'imgBox' + i;
        imgBox.className = 'imageBox';
        theImg = document.createElement('div');
        theImg.id = 'img_' + i;
        theImg.className = 'imageBox_theImage';
        imgBox.appendChild(theImg);

        imageListWrapper.appendChild(imgBox);
        if (i === uploadMaxNumber - 1) {
            lastSpacer = spacer(spacerNo);
            lastSpacer.style.height = "7px";
            imageListWrapper.appendChild(lastSpacer);
        }
    }

    imageListWrapper.style.padding = '5px 7px 0px 5px';
    document.getElementById('imageInfoBox').style.height = '298px';
    document.getElementById('imageInfoBox').style.width = '130px';
}

function setImageCount() {
    imageCompleted++;
    document.getElementById('imageCount').innerHTML = imageCompleted.toString();
}

function getImageCount() {
    return imageCompleted;
}

function allowedMaxImage() {
    return uploadMaxNumber - getImageCount();
}

function getUploadedCount() {
    return imageListWrapper.getElementsByTagName('img').length;
}

function uploadedImageCount() {
    imageCompleted = getUploadedCount();
    document.getElementById('imageCount').innerHTML = imageCompleted.toString();
}

function getTopPos(inputObj) {
    // ----------------------------------------------------------------------------------
    var returnValue = inputObj.offsetTop;

    inputObj = inputObj.offsetParent;
    while (inputObj) {
        if (inputObj.tagName.toLowerCase() !== 'html') {
            returnValue += inputObj.offsetTop - inputObj.scrollTop;
            if (browser.msie) {
                returnValue += inputObj.clientTop;
            }
        }
        inputObj = inputObj.offsetParent;
    }
    return returnValue;
}

function getLeftPos(inputObj) {
    // ----------------------------------------------------------------------------------
    var returnValue = inputObj.offsetLeft;

    inputObj = inputObj.offsetParent;
    while (inputObj) {
        if (inputObj.id !== 'imageListWrapper') {
            returnValue += inputObj.offsetLeft;
        }
        inputObj = inputObj.offsetParent;
    }
    return returnValue;
}

function getDivCoordinates() {
    // ----------------------------------------------------------------------------------
    var imgBox = imageListWrapper.getElementsByTagName('DIV'),
        i = 0;

    for (; i < imgBox.length; i++) {
        if ((imgBox[i].className === 'imageBox' || imgBox[i].className === 'imageBoxHighlighted') && imgBox[i].id) {
            divXPositions[imgBox[i].id] = getLeftPos(imgBox[i]);
            divYPositions[imgBox[i].id] = getTopPos(imgBox[i]);
            divWidth[imgBox[i].id]  = imgBox[i].offsetWidth;
            divHeight[imgBox[i].id] = imgBox[i].offsetHeight;
        }
    }
}

function reOrder() {
    // ----------------------------------------------------------------------------------
    var imgBox = imageListWrapper.getElementsByTagName('div'),
        imgNum = 0, i, spacer, breakline = [];

    for (i = 0; i < imgBox.length; i++) {
        if (imgBox[i].id.indexOf('imgBox') === -1) {
            continue;
        }

        imgBox[i].className = 'imageBox';
        imgBox[i].firstChild.className = 'imageBox_theImage';

        if (imgNum > 0 && imgNum % 4 === 0) {
            breakline.push(imgBox[i].id);
        }

        imgNum++;
    }

    for (i = 0; i < breakline.length; i++) {
        spacer = document.getElementById('spacer' + (i + 1));
        if (i + 1 === breakline.length) {
            imageListWrapper.appendChild(spacer);
        } else {
            imageListWrapper.insertBefore(spacer, document.getElementById(breakline[i]));
        }
    }
}

function showDelete() {
    var self = this, btn;

    if (readyToMove) {
        return;
    }

    getDivCoordinates();
    self.className = 'imageBox_theImage_over';
    btn = document.getElementById('removeImageButton');
    btn.style.left = showThumbnailSize.width - parseInt(btn.style.width, 10) - 1 + 'px';
    btn.style.top = '-1px';

    self.appendChild(btn);
    btn.style.display = 'block';

    btn.onmouseover = function (ev) {
        oEditor.stopEvent(ev);
        this.style.display = 'block';
        this.className = 'removeButton_over';
        self.className = 'imageBox_theImage_over';
    };
    btn.onmouseout = function () {
        this.className = 'removeButton';
    };
    btn.onmousedown = function (ev) {
        var images = self.getElementsByTagName('img'), i, moveobj, target;

        for (i = 0; i < images.length; i++) {
            self.removeChild(images[i]);
        }

        self.removeChild(self.firstChild);
        self.className = 'imageBox_theImage';

        if (self.parentNode.nextSibling && self.parentNode.nextSibling.id) {
            moveobj = self.parentNode.nextSibling;
            target = self.parentNode;

            while (moveobj !== null) {
                if (moveobj.firstChild && !moveobj.firstChild.firstChild) {
                    break;
                }
                if (/^spacer/.test(moveobj.id)) {
                    moveobj = moveobj.nextSibling;
                    continue;
                }
                imageListWrapper.insertBefore(moveobj, target);
                moveobj = target.nextSibling;
            }
        }

        reOrder();
        uploadedImageCount();
        this.style.display = 'none';
        document.body.appendChild(ev.target);
        oEditor.removeEvent(self, 'mouseover', showDelete);
        self.removeAttribute('title');
    };
}

function hideDelete() {
    // ----------------------------------------------------------------------------------
    document.getElementById('removeImageButton').style.display = 'none';
}

function startUpload(list) {
    // ----------------------------------------------------------------------------------
    var el = imageListWrapper.getElementsByTagName('div'), i, imgBox,
        count = 0, len = list.length;

    for (i = 0; i < el.length; i++) {
        imgBox = el[i];
        if (imgBox.className !== 'imageBox_theImage') {
            continue;
        }
        if (count === len) {
            break;
        }
        if (!imgBox.firstChild || imgBox.firstChild.tagName.toLowerCase()  !== 'img') {
            imgBox.style.backgroundImage = "url('" + uploadImagePath + "/loader.gif')";
            list[count++].boxElem = imgBox;
        }
    }
}

function fileFilterError(file) {
    alert("선택하신 '" + file + "' 파일은 전송할 수 없습니다.\n" +
       "gif, png, jpg, webp 사진 파일만 전송할 수 있습니다.");
}

function imgComplete(img, imgSize, boxId) {
    var resizeW, resizeH, M, elem;
    img.setAttribute("border", '0');

    if (imgSize.width > showThumbnailSize.width || imgSize.height > showThumbnailSize.height) {
        if (imgSize.width > imgSize.height) {
            resizeW = imgSize.width > showThumbnailSize.width ? showThumbnailSize.width : imgSize.width;
            resizeH = Math.round(imgSize.height * resizeW / imgSize.width);
        } else {
            resizeH = imgSize.height > showThumbnailSize.height ? showThumbnailSize.height : imgSize.height;
            resizeW = Math.round(imgSize.width * resizeH / imgSize.height);
        }

        if (resizeH > showThumbnailSize.height) {
            resizeH = imgSize.height > showThumbnailSize.height ? showThumbnailSize.height : imgSize.height;
            resizeW = Math.round(imgSize.width * resizeH / imgSize.height);
        }

    } else {
        resizeW = imgSize.width;
        resizeH = imgSize.height;
    }

    img.style.width  = resizeW - 2 + 'px';
    img.style.height = resizeH - 2 + 'px';
    img.style.margin = "1px";

    if (resizeW < showThumbnailSize.width) {
        M = showThumbnailSize.width - resizeW;
        img.style.marginLeft = Math.round(M / 2) + 'px';
    }

    if (resizeH < showThumbnailSize.height) {
        M = showThumbnailSize.height - resizeH;
        img.style.marginTop = Math.round(M / 2) + 'px';
    }

    elem = document.getElementById(boxId);
    boxId = boxId.replace(/img_/, '');

    if (boxId % 12 === 0) {
        imageListWrapper.scrollTop = elem.offsetTop - 6;
    }

    elem.style.backgroundImage = "url('" + uploadImagePath + "/dot.gif')";
    setElemTitle(elem, imgSize.width, imgSize.height);
    oEditor.addEvent(elem, 'mouseover', showDelete);
    elem.onmouseout = function () {
        this.className = 'imageBox_theImage';
        hideDelete();
    };

    setImageCount();
}

function setElemTitle(elem, width, height) {
    elem.setAttribute('title', 'Width: ' + width + 'px, Height: ' + height + 'px');
}

function showUploadWindow() {
    // ----------------------------------------------------------------------------------
    var uploadWindow  = document.getElementById("uploadWindow"),
        uploadWindowWidth = 700,
        winWidth, el, i, j, imgBox, img;

    if (!oEditor.undefined(window.innerWidth)) {
        winWidth  = window.innerWidth;
    } else if (document.documentElement &&
        !oEditor.undefined(document.documentElement.clientWidth) &&
             document.documentElement.clientWidth !== 0) {
        winWidth = document.documentElement.clientWidth;
    } else if (document.body && !oEditor.undefined(document.body.clientWidth)) {
        winWidth = document.body.clientWidth;
    } else {
        alert('현재 브라우저를 지원하지 않습니다.');
        return;
    }

    uploadWindow.style.left = winWidth / 2 - uploadWindowWidth / 2 + 'px';
    uploadWindow.style.display = "block";
    uploadWindow.style.width = uploadWindowWidth + 'px';

    if (modifyImages.length > 0) {
        el = imageListWrapper.getElementsByTagName('div');
        for (i = 0; i < modifyImages.length; i++) {
            if (i > 7) {
                break;
            }

            for (j = 0; j < el.length; j++) {
                imgBox = el[j];
                if (imgBox.className !== 'imageBox_theImage') {
                    continue;
                }
                if (imgBox.firstChild && imgBox.firstChild.src === modifyImages[i]) {
                    break;
                }
                if (imgBox.firstChild === null) {
                    img = new Image();
                    img.src = modifyImages[i];
                    img.border = 0;
                    img.alt = '';
                    img.style.width = '120px';
                    img.style.height = '90px';
                    imgBox.appendChild(img);
                    break;
                }
            }
        }
    }
}

function removeImages() {
    var images = [], i, j, theImage, img, remove;
    document.body.appendChild(document.getElementById('removeImageButton'));

    for (i = 0; i < uploadMaxNumber; i++) {
        theImage = document.getElementById('img_' + i);
        if (theImage.hasChildNodes() && theImage.firstChild.tagName.toLowerCase() === 'img') {
            images.push(theImage);
        }
    }

    for (i = 0; i < images.length; i++) {
        img = images[i];
        if (img.firstChild !== null) {
            oEditor.removeEvent(img, 'mouseover', showDelete);
            remove = img.getElementsByTagName('img');

            for (j = 0; j < remove.length; j++) {
                img.removeChild(remove[j]);
            }

            img.parentNode.className = 'imageBox';
            img.removeAttribute('title');
            oEditor.removeEvent(img, 'mouseover', showDelete);
        }
    }
    uploadedImageCount();
    imageCompletedList = [];
}

function removeImage() {
    // ----------------------------------------------------------------------------------
    var i, theImage, found = false;

    for (i = 0; i < uploadMaxNumber; i++) {
        theImage = document.getElementById('img_' + i);
        if (theImage.hasChildNodes() && theImage.firstChild.tagName.toLowerCase() === 'img') {
            found = true;
            break;
        }
    }

    if (found) {
        if (!confirm('추가하신 사진이 있습니다. 사진 넣기를 취소하시겠습니까?')) {
            return false;
        }
        removeImages();
    }

    return true;
}

function closeWindow() {
    // ----------------------------------------------------------------------------------
    if (removeImage()) {
        popupClose();
    }
}

function cancelEvent() {
    // ----------------------------------------------------------------------------------
    return false;
}

function startMoveTimer() {
    // ----------------------------------------------------------------------------------
    var subElements, newDiv;

    if (moveTimer >= 0 && moveTimer < 10) {
        moveTimer++;
        setTimeout(startMoveTimer(), 8);
    }

    if (moveTimer === 5) {
        getDivCoordinates();
        subElements = dragDropDiv.getElementsByTagName('div');
        if (subElements.length > 0) {
            dragDropDiv.removeChild(subElements[0]);
        }

        dragDropDiv.style.display = 'block';
        newDiv = activeImage.cloneNode(true);
        newDiv.className = 'imageBox';
        newDiv.style.opacity = 0.5;

        newDiv.id = '';
        newDiv.style.padding = '2px';
        dragDropDiv.appendChild(newDiv);

        dragDropDiv.style.top = tmpTop + 'px';
        dragDropDiv.style.left = tmpLeft + 'px';
    }

    return false;
}

function getMouseButtn(e) {
    var code;
    e = e || window.event;
    code = e.button;

    if (code) {
        if (browser.msie && browser.version < 9) {
            code = code === 1 ? 0 : code === 4 ? 1 : code;
        }
    }

    return code;
}

function selectImage(e) {
    // ----------------------------------------------------------------------------------
    var el = this.parentNode.firstChild.firstChild, obj;

    if (!el) {
        return;
    }

    e = e || window.event;
    if (getMouseButtn(e) === 2) {
        return;
    }

    obj = this.parentNode;
    hideDelete();

    obj.className = 'imageBoxHighlighted';
    activeImage = obj;
    readyToMove = true;
    moveTimer = 0;

    tmpLeft = e.clientX + Math.max(document.body.scrollLeft, document.documentElement.scrollLeft);
    tmpTop = e.clientY + Math.max(document.body.scrollTop, document.documentElement.scrollTop);

    startMoveTimer();
    return false;
}

function dragDropEnd() {
    // ----------------------------------------------------------------------------------
    var parentObj, chkObj, turn = false;

    readyToMove = false;
    moveTimer = -1;
    dragDropDiv.style.display = 'none';
    insertionMarker.style.display = 'none';

    if (!activeImage) {
        return;
    }

    if (destinationObject && destinationObject !== activeImage) {
        parentObj = destinationObject.parentNode;
        chkObj = destinationObject.previousSibling;
        turn = false;

        if (chkObj === null) {
            chkObj = imageListWrapper.firstChild;
            turn = true;
        }

        if (chkObj.id.indexOf('spacer') !== -1) {
            chkObj = chkObj.previousSibling;
        }

        if (chkObj.firstChild.firstChild === null) {
            reOrder();
            return;
        }

        if (chkObj && chkObj.id !== null) {
            while (chkObj) {
                if (chkObj.firstChild.firstChild !== null) {
                    break;
                }
                chkObj = chkObj.previousSibling;
            }
            destinationObject = turn ? chkObj : chkObj.nextSibling;
        }

        parentObj.insertBefore(activeImage, destinationObject);
        reOrder();

        activeImage = null;
        destinationObject = null;
        getDivCoordinates();

        return false;
    }

    activeImage.className = "imageBox";
    return true;
}

function dragDropMove(e) {
    // ----------------------------------------------------------------------------------
    var elementFound = false, prop, offsetX, offsetY, leftPos, topPos;

    if (moveTimer === -1 || !readyToMove) {
        return;
    }

    e = e || window.event;

    leftPos = e.clientX + document.documentElement.scrollLeft - eventDiff_x;
    topPos = e.clientY + document.documentElement.scrollTop - eventDiff_y;

    dragDropDiv.style.top = topPos + 'px';
    dragDropDiv.style.left = leftPos + 'px';

    leftPos = leftPos + eventDiff_x;
    topPos = topPos + eventDiff_y;

    if (getMouseButtn(e) !== 0) {
        dragDropEnd();
    }

    for (prop in divXPositions) {
        if (!divXPositions.hasOwnProperty(prop) || divXPositions[prop].className === 'clear') {
            continue;
        }

        if (divXPositions[prop] < leftPos &&
         divXPositions[prop] + divWidth[prop] * 0.7 > leftPos &&
          divYPositions[prop] < topPos &&
         divYPositions[prop] + divWidth[prop] > topPos) {
            if (browser.msie) {
                offsetX = offsetX_marker;
                offsetY = offsetY_marker;
            } else {
                offsetX = geckoOffsetX_marker;
                offsetY = geckoOffsetY_marker;
            }

            insertionMarker.style.top = divYPositions[prop] + offsetY + 'px';
            insertionMarker.style.left = divXPositions[prop] + offsetX + 'px';
            insertionMarker.style.display = 'block';
            destinationObject = document.getElementById(prop);
            elementFound = true;
            break;
        }
    }

    if (!elementFound) {
        insertionMarker.style.display = 'none';
        destinationObject = false;
    }

    return false;
}

function initGallery() {
    // ----------------------------------------------------------------------------------
    var imgBox = imageListWrapper.getElementsByTagName('div'),
        i;

    for (i = 0; i < imgBox.length; i++) {
        if (imgBox[i].className === 'imageBox_theImage') {
            imgBox[i].onmousedown = selectImage;
        }
    }

    document.body.onselectstart = cancelEvent;
    document.body.ondragstart = cancelEvent;
    document.body.onmouseup = dragDropEnd;
    document.body.onmousemove = dragDropMove;

    dragDropDiv = document.getElementById('dragDropContent');
    insertionMarker = document.getElementById('insertionMarker');
    getDivCoordinates();
}

function doSubmit() {
    // ----------------------------------------------------------------------------------
    var el = imageListWrapper.getElementsByTagName('div'),
        imageArray = [],
        num = 0,
        elem = document.getElementById('id_alignment').elements,
        imgParagraph = false,
        useSpacer = false,
        imgAlign = 'top', i, imgBox, input;

    for (i = 0; i < elem.length; i++) {
        input = elem[i];
        switch (input.name) {
            case "alignment" :
                if (input.checked) {
                    imgAlign = input.value;
                }
                break;
            case "para" :
                imgParagraph = input.checked;
                break;
            case "use_spacer" :
                useSpacer = input.checked;
                break;
        }
    }

    for (i = 0; i < el.length; i++) {
        imgBox = el[i];
        if (imgBox.className !== "imageBox_theImage") {
            continue;
        }

        if (imgBox.firstChild !== null) {
            imageArray[num] = imageCompletedList[imgBox.id];

            if (imgAlign === "break") {
                imageArray[num].alt = "break";
            } else {
                imageArray[num].alt = '';
                imageArray[num].align = imgAlign;
            }

            num++;
        }
    }

    if (imageArray.length > 0) {
        oEditor.doInsertImage(imageArray, imgParagraph, useSpacer);
    }
    oEditor.popupWinClose();
}

function selectedFiles(evt) {
    var upload = new DoUpload(),
        files = evt.target.files || [];

    oEditor.stopEvent(evt);
    if (files) {
        upload.select(files);
    }
}

function DoUpload() {
    this.list = [];
    this.reader = new FileReader();
    this.URL = window.URL || window.webkitURL;

    this.reader.onprogress = null;
    this.reader.onloadstart = null;
    this.reader.onabort = null;
    this.reader.onerror = null;

    this.MyBlob = (function () {
        var key, blob, self = this;
        function MYBLOB(blob) {
            var url = null;
            this.blob = blob;
            blob = null;

            this.getURL = function () {
                if (url) {
                    return url;
                }
                url = self.URL.createObjectURL(this.blob);
                return url;
            };
            this.dispose = function () {
                if (url) {
                    url = self.URL.revokeObjectURL(url);
                }
                if (typeof this.blob.msClose !== 'undefined') {
                    this.blob.msClose();
                }
                this.blob = null;
                if (debug) {
                    console.log("Blob Data Clear");
                }
            };
        }

        blob = new Blob();
        for (key in blob) {
            if ({}.hasOwnProperty.call(blob, key)) {
                (function (key) {
                    Object.defineProperty(MYBLOB.prototype,
                        key,
                        {
                            enumerable: true,
                            configurable: true,
                            get: function () {
                                return this.blob[key];
                            }
                        }
                    );
                }(key));
            }
        }

        key = undefined;
        return MYBLOB;
    }());

    return this;
}

DoUpload.prototype = {
    select: function (files) {
        var self = this,
            num = files.length,
            i = 0,
            file = null;

        if (num > allowedMaxImage()) {
            num = allowedMaxImage();
        }

        for (; i < num; i++) {
            file = files[i];

            if (!file.type.match(fileTypeRe)) {
                fileFilterError(file.name);
                continue;
            }
            this.list.push(file);
        }

        if (this.list.length < 1) {
            return;
        }

        this.reader.addEventListener("error", function (evt) {
            self.onReadDataErrorHandler(evt);
        }, false);

        this.reader.onloadend = function (evt) {
            self.dataLoadHandler(evt);
        };

        setResizeWidth();
        startUpload(this.list);

        this.load();
    },

    getDateTime : function () {
        var date = new Date(),
            year = date.getFullYear(),
            month = date.getMonth() + 1,
            day = date.getDate(),
            hours = date.getHours(),
            minutes = date.getMinutes(),
            seconds = date.getSeconds();

        return String(10000 * year + 100 * month + day +
            ('0' + hours).slice(-2) + ('0' + minutes).slice(-2) + ('0' + seconds).slice(-2));
    },

    makeFilename : function (type) {
        var chars = "abcdefghiklmnopqrstuvwxyz",
            len = 8, clen = chars.length, rData = '', i, rnum;

        for (i = 0; i < len; i++) {
            rnum = Math.floor(Math.random() * clen);
            rData += chars.substring(rnum, rnum + 1);
        }

        if (type !== '') {
            rData += type.toLowerCase();
        }

        return this.getDateTime() + '_' + rData;
    },

    getOrientation : function (data) {
        var view = new DataView(data),
            length = view.byteLength,
            offset = 2,
            marker, little, tags, i;

        // JPEG가 아닌 경우, 알 수 없음
        if (view.getUint16(0, false) !== 0xffd8) {
            return -2;
        }

        while (offset < length) {
            // 알 수 없음
            if (view.getUint16(offset + 2, false) <= 8) {
                return -1;
            }

            marker = view.getUint16(offset, false);
            offset += 2;

            if (marker === 0xffe1) {
                // 알 수 없음
                if (view.getUint32(offset += 2, false) !== 0x45786966) {
                    return -1;
                }

                little = view.getUint16(offset += 6, false) === 0x4949;
                offset += view.getUint32(offset + 4, little);
                tags = view.getUint16(offset, little);
                offset += 2;

                for (i = 0; i < tags; i++) {
                    if (view.getUint16(offset + i * 12, little) === 0x0112) {
                        return view.getUint16(offset + i * 12 + 8, little);
                    }
                }
            } else if ((marker & 0xff00) !== 0xff00) {
                break;
            } else {
                offset += view.getUint16(offset, false);
            }
        }
        // 알 수 없음
        return -1;
    },

    NewBlob : function (data, datatype) {
        var blob = null, blobb;
        try {
            blob = new Blob([data], {type: datatype});
        } catch (e) {
            window.BlobBuilder = window.BlobBuilder
                || window.WebKitBlobBuilder
                || window.MozBlobBuilder
                || window.MSBlobBuilder;

            if (e.name === 'TypeError' && window.BlobBuilder) {
                // eslint-disable-next-line no-undef
                blobb.append(data);
                blob = blobb.getBlob(datatype);
                console.log("TypeError");
            } else if (e.name === "InvalidStateError") {
                console.log("InvalidStateError");
            } else {
                console.log("Error");
            }
        }
        return blob;
    },

    imageResize : function (image, filetype, resize_w, orientation, addWaterMark) {
        var canvas = document.createElement("canvas"),
            ctx = canvas.getContext("2d"),
            source_w = image.width,
            source_h = image.height,
            resize_h, ratio_w, ratio_h, ratio_w_half, ratio_h_half,
            source_img, resize_img, source_data, resize_data, j, i,
            x2, weight, weights, weights_alpha, gx_a, gx_b, gx_g, gx_r, 
            center_x, center_y, x_start, x_stop,
            y_start, y_stop, y, dy, part_w, x, dx, w, pos_x, gl, imageData = null;

        // 카메라 로테이션 보정
        if (orientation > 0 && !supportImageOrientation) {
            if ([5,6,7,8].indexOf(orientation) > -1) {
                canvas.width = source_h;
                canvas.height = source_w;
            } else {
                canvas.width = source_w;
                canvas.height = source_h;
            }

            switch (orientation) {
                case 2 : ctx.transform(-1, 0, 0, 1, source_w, 0); break;
                case 3 : ctx.transform(-1, 0, 0, -1, source_w, source_h); break;
                case 4 : ctx.transform(1, 0, 0, -1, 0, source_h); break;
                case 5 : ctx.transform(0, 1, 1, 0, 0, 0); break;
                case 6 : ctx.transform(0, 1, -1, 0, source_h, 0); break;
                case 7 : ctx.transform(0, -1, -1, 0, source_h, source_w); break;
                case 8 : ctx.transform(0, -1, 1, 0, 0, source_w); break;
                default: break;
            }

            ctx.drawImage(image, 0, 0, source_w, source_h);
            imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            ctx.restore();
            source_w = canvas.width;
            source_h = canvas.height;
        }

        if (source_w > resize_w) {
            resize_h = Math.ceil(resize_w / source_w * source_h);

            try {
                gl = GLScale({
                    width: resize_w, height: resize_h
                });
                gl(imageData || image, function (gl_canvas) {
                    canvas = gl_canvas;
                });
            } catch (ignore) {
                canvas.width = source_w;
                canvas.height = source_h;

                if (imageData) {
                    ctx.putImageData(imageData, 0, 0);
                } else {
                    ctx.drawImage(image, 0, 0);
                }

                ratio_w = source_w / resize_w;
                ratio_h = source_h / resize_h;
                ratio_w_half = Math.ceil(ratio_w / 2);
                ratio_h_half = Math.ceil(ratio_h / 2);
                source_img = ctx.getImageData(0, 0, source_w, source_h);
                resize_img = ctx.createImageData(resize_w, resize_h);
                source_data = source_img.data;
                resize_data = resize_img.data;

                for (j = 0; j < resize_h; j++) {
                    for (i = 0; i < resize_w; i++) {
                        x2 = (i + j * resize_w) * 4;
                        weight = weights = weights_alpha = 0;
                        gx_r = gx_g = gx_b = gx_a = 0;
                        center_y = (j + 0.5) * ratio_h;

                        x_start = Math.floor(i * ratio_w);
                        x_stop = Math.ceil((i + 1) * ratio_w);
                        y_start = Math.floor(j * ratio_h);
                        y_stop = Math.ceil((j + 1) * ratio_h);

                        x_stop = Math.min(x_stop, source_w);
                        y_stop = Math.min(y_stop, source_h);

                        for (y = y_start; y < y_stop; y++) {
                            dy = Math.abs(center_y - (y + 0.5)) / ratio_h_half;
                            center_x = (i + 0.5) * ratio_w;
                            part_w = dy * dy;

                            for (x = x_start; x < x_stop; x++) {
                                dx = Math.abs(center_x - (x + 0.5)) / ratio_w_half;
                                w = Math.sqrt(part_w + dx * dx);
                                if (w >= 1) {
                                    continue;
                                }
                                // Hermite 필터
                                weight = 2 * w * w * w - 3 * w * w + 1;
                                pos_x = 4 * (x + y * source_w);
                                // 알파 채널
                                gx_a += weight * source_data[pos_x + 3];
                                weights_alpha += weight;

                                if (source_data[pos_x + 3] < 255) {
                                    weight = weight * source_data[pos_x + 3] / 250;
                                }

                                gx_r += weight * source_data[pos_x];
                                gx_g += weight * source_data[pos_x + 1];
                                gx_b += weight * source_data[pos_x + 2];
                                weights += weight;
                            }
                        }
                        resize_data[x2] = gx_r / weights;
                        resize_data[x2 + 1] = gx_g / weights;
                        resize_data[x2 + 2] = gx_b / weights;
                        resize_data[x2 + 3] = gx_a / weights_alpha;
                    }
                }
                canvas.width = resize_w;
                canvas.height = resize_h;
                ctx.putImageData(resize_img, 0, 0);
            }
        } else {
            canvas.width = source_w;
            canvas.height = source_h;
            ctx.drawImage(image, 0, 0);
        }

        if (this.reader.watermark && addWaterMark) {
            ctx.globalAlpha = oEditor.config.imgWaterMarkAlpha;
            ctx.drawImage(this.reader.watermark,
                canvas.width - this.reader.watermark.width, canvas.height - this.reader.watermark.height);
        }
        
        return canvas.toDataURL(filetype, oEditor.config.imgJpegQuality);
    },

    canvasToBlob : function (bitmapData, mimetype) {
        var i = 0,
            intArray = [],
            len = bitmapData.length,
            raw = atob(bitmapData.split(',')[1]);

        for (; i < len; i++) {
            intArray.push(raw.charCodeAt(i));
        }
        return new Blob([new Uint8Array(intArray)], {type: mimetype});
    },

    makeThumbnail : function (image, type, name, orientation) {
        var width,
            xhr = new XMLHttpRequest(),
            data = new FormData(),
            bitmapData, file;

        xhr.open('POST', uploadScript, true);
        width = oEditor.config.thumbnailWidth;

        bitmapData = this.imageResize(image, type, width, orientation);
        file = this.canvasToBlob(bitmapData, type);
        data.append(inputFileName, file, 'thumb_' + name); // RFC Level 2

        xhr.addEventListener("loadend", function () {
            // loadend
        }, false);

        xhr.addEventListener("error", function () {
            alert("Thumbnail 파일 전송 중 오류:");
        }, false);

        xhr.send(data);
    },

    dataLoadHandler: function (evt) {
        var self = this,
            filename = evt.target.file.name,
            filetype = evt.target.file.type,
            file = evt.target.file,
            blob, image, orientation = 1,
            slice = 64 * 1024;

        if (slice > file.size - 1) {
            slice = file.size;
        }

        if (evt.target.readyState === FileReader.DONE) {
            blob = new self.MyBlob(self.NewBlob(evt.target.result, filetype));
            orientation = self.getOrientation(evt.target.result.slice(0, slice));

            image = new Image();
            image.onload = function () {
                var bitmapData = null,
                    data = new FormData(),
                    fileFormat,
                    imgBox = file.boxElem,
                    imgInfo = {},
                    randomName,
                    xhr = new XMLHttpRequest();

                xhr.open('POST', uploadScript, true);

                fileFormat = filename.substring(filename.lastIndexOf('.'));
                if (imageResizeWidth > 0 && fileFormat !== '.gif') {
                    bitmapData = self.imageResize(this, filetype, imageResizeWidth, orientation, true);
                    file = self.canvasToBlob(bitmapData, filetype);
                }

                randomName = self.makeFilename(fileFormat);

                data.append('origname', filename);
                data.append(inputFileName, file, randomName); // RFC Level 2

                if (debug) {
                    console.log('Successed: ' + filename);
                }

                xhr.addEventListener("error", function (evt) {
                    alert("파일 전송 중 오류: " + evt.toString());
                }, false);

                xhr.addEventListener("loadend", function onLoadendImageHandler(xhrevt) {
                    if (xhrevt.target.readyState === xhrevt.target.DONE) {
                        if (oEditor.config.makeThumbnail) {
                            self.makeThumbnail(image, filetype, randomName, orientation, false);
                        }
                    }
                    image.src = '';
                    image = null;
                }, false);

                xhr.addEventListener("load", function (xhrevt) {
                    var jsonText, jsonData, img, onLoadHandler;
                    data = null;

                    if (xhrevt.target.status === 200) {
                        jsonText = decodeURI(oEditor.trimSpace(this.responseText));
                        jsonText = jsonText.replace(/\+/g, ' ').replace(/\\/g, '\\\\');
                        jsonData = JSON.parse(jsonText);

                        onLoadHandler = function () {
                            imgInfo = {
                                fileName: jsonData.fileName,
                                filePath: jsonData.filePath,
                                fileSize: jsonData.fileSize,
                                fileUrl: jsonData.fileUrl,
                                origName: filename,
                                origSize: file.size,
                                height: img.height,
                                width: img.width
                            };
                            imageCompletedList[imgBox.id] = imgInfo;
                            imgComplete(this, imgInfo, imgBox.id);
                            imgBox.appendChild(img);

                            if (debug) {
                                console.log('Image URL: ' + img.src + ', size:' + file.size);
                            }

                            setTimeout(function () {
                                self.load();
                            }, 100);

                            if (debug) {
                                console.log('Uploaded');
                            }
                        };
                        img = new Image();
                        img.onload = onLoadHandler;
                        img.src = decodeURIComponent(jsonData.fileUrl);
                    } else {
                        alert("HTTP 오류: " + xhr.status);
                    }
                }, false);

                blob.dispose();
                blob = null;
                xhr.send(data);
            };
            image.src = blob.getURL();
        }
    },

    onReadDataErrorHandler: function (evt) {
        var status = '';
        switch (evt.target.error.code) {
            case evt.target.error.NOT_FOUND_ERR:
                status = "파일을 찾을 수 없습니다.";
                break;
            case evt.target.error.NOT_READABLE_ERR:
                status = "파일을 읽을 수 없습니다.";
                break;
            case evt.target.error.ABORT_ERR:
                status = "파일 읽기가 중지되었습니다.";
                break;
            case evt.target.error.SECURITY_ERR:
                status = "파일이 잠겨 있습니다.";
                break;
            case evt.target.error.ENCODING_ERR:
                status = "data:// URL의 파일 인코딩 길이가 너무 깁니다.";
                break;
            default:
                status = "파일 읽기 오류: " + evt.target.error.code;
        }
        this.removeEventListener('error', this.onReadDataErrorHandler);
        alert("'" + evt.target.filename + "' " + status);
    },

    load: function () {
        var file = this.list.shift(), self = this, watermark = null;

        if (file) {
            if (debug) {
                console.log('File ' + this.index + ', Name: ' + file.name + ', Size: ' + file.size);
            }
            this.reader.file = file;
            this.reader.watermark = null;

            if (oEditor.config.imgWaterMarkUrl !== '' && oEditor.config.imgWaterMarkUrl !== null) {
                watermark = new Image();
                watermark.onerror = function () {
                    alert('워터마크 이미지를 읽을 수 없습니다. (' + oEditor.config.imgWaterMarkUrl + ')');
                    self.reader.readAsArrayBuffer(file);
                };
                watermark.onload = function () {
                    self.reader.watermark = this;
                    self.reader.readAsArrayBuffer(file);
                };
                watermark.src = oEditor.config.imgWaterMarkUrl;
            } else {
                this.reader.readAsArrayBuffer(file);
            }
        } else {
            this.clear();
        }
    },

    clear: function () {
        var inputFile = document.getElementById('inputImageUpload'),
            theForm = document.createElement('form'),
            fileSelectButton = document.getElementById('fileSelectButton');

        this.list = [];

        theForm.appendChild(inputFile);
        theForm.reset();
        fileSelectButton.parentNode.insertBefore(inputFile, fileSelectButton);
        fileSelectButton.style.marginLeft = '-1px';
    }
};

function fileSelectDrop(evt) {
    var files,
        upload = new DoUpload();

    oEditor.stopEvent(evt);
    this.className = "imageListWrapperHtml5";

    files = evt.dataTransfer.files;
    upload.select(files);
}

function dragOver(ev) {
    oEditor.stopEvent(ev);
    this.className = "dragOver";
}

function dragOut(ev) {
    oEditor.stopEvent(ev);
    this.className = "imageListWrapperHtml5";
}

function setResizeWidth() {
    var value = oEditor.trimSpace(imageResizeInput.value);
    if (value) {
        value = Math.ceil(parseInt(value, 10));
        if (!isNaN(value) && value < oEditor.config.imgMaxWidth) {
            imageResizeWidth = value;
        } else {
            imageResizeInput.value = '';
            imageResizeWidth = oEditor.config.imgMaxWidth;
            imageResizeInput.setAttribute('placeholder', oEditor.config.imgMaxWidth.toString());
        }
    }
}

function init(dialog) {
    var dlg, i, elem, input, select, value, name, xhr_f, xhr_v, tmpcanvas, glicon, testImg;

    oEditor = this;
    oEditor.dialog = dialog;
    dlg = new Dialog(oEditor);
    browser = oEditor.getBrowser();

    uploadImagePath = oEditor.config.iconPath + 'imageUpload';
    uploadMaxNumber = oEditor.config.imgUploadNumber;
    uploadScript = oEditor.config.editorPath + 'imageUpload/upload.php';
    imageListWrapper = document.getElementById("imageListWrapper");
    imageResizeInput = document.getElementById('idResizeWidth');
    select = document.getElementById('idResizeSelectBox');

    if (oEditor.config.imgMaxWidth > 0) {
        imageResizeWidth = oEditor.config.imgMaxWidth;
        for (i = 0; i < oEditor.config.imgResizeValue.length; i++) {
            name = value = oEditor.config.imgResizeValue[i];
            if (value > oEditor.config.imgMaxWidth) {
                continue;
            }
            if (value === -1) {
                name = '<입력>';
            }
            select.options[select.options.length] = new Option(name, value, false, value === oEditor.config.imgResizeSelected);
        }
        select.onchange = function () {
            if (this.value < 0) {
                document.getElementById('idUserInputWrapper').style.display = '';
                imageResizeInput.value = '';
                imageResizeWidth = oEditor.config.imgMaxWidth;
                imageResizeInput.focus();
            } else {
                document.getElementById('idUserInputWrapper').style.display = 'none';
                imageResizeWidth = this.value;
            }
        };
        imageResizeInput.setAttribute('placeholder', imageResizeWidth.toString());
        imageResizeWidth = select.value;
    } else {
        select.options[0] = new Option('원본', 0);
        select.setAttribute('disabled', 'disabled');
        imageResizeWidth = 0;
    }

    document.getElementById("maxImageNum").appendChild(document.createTextNode(uploadMaxNumber.toString()));

    button = [
        { alt: "", img: 'submit.gif', cmd: doSubmit, hspace: 2 },
        { alt: "", img: 'cancel.gif', cmd: closeWindow, hspace: 2 }
    ];

    dlg.setDialogHeight(370);
    dlg.showButton(button);
    showContents();
    initGallery();
    showUploadWindow();
    createInsertionMaker();

    oEditor.addEvent(imageListWrapper, 'dragover', dragOver);
    oEditor.addEvent(imageListWrapper, 'dragleave', dragOut);
    oEditor.addEvent(imageListWrapper, 'drop', fileSelectDrop);

    elem = document.getElementById('id_alignment').elements;

    for (i = 0; i < elem.length; i++) {
        if (elem[i].name === "alignment" && elem[i].value === oEditor.config.imgDefaultAlign) {
            elem[i].checked = "checked";
            break;
        }
    }

    if (browser.mobile) {
        input = document.getElementById('inputImageUpload');
        input.setAttribute('capture', 'filesystem');
    }

    tmpcanvas = document.createElement('canvas');
    if (tmpcanvas.getContext('webgl', {preserveDrawingBuffer: true}) ||
        tmpcanvas.getContext('experimental-webgl', {preserveDrawingBuffer: true}))
    {
        useWebGL = true;
        GLScale.Hermite = { vertex: '', fragment: '' };
        xhr_v = new XMLHttpRequest();
        xhr_f = new XMLHttpRequest();
        xhr_f.open('POST', 'js/fragment-shader.glsl', true);
        xhr_f.addEventListener("load", function (evt) {
            if (evt.target.status === 200) {
                GLScale.Hermite.fragment = this.responseText;
            } else {
                useWebGL = false;
            }
        });
        xhr_v.open('POST', 'js/vertex-shader.glsl', true);
        xhr_v.addEventListener("load", function (evt) {
            if (evt.target.status === 200) {
                GLScale.Hermite.vertex = this.responseText;
            } else {
                useWebGL = false;
            }
        });
        xhr_f.send();
        xhr_v.send();
    }

    glicon = new Image();
    glicon.className = 'webgl_logo';
    glicon.src = uploadImagePath + (useWebGL ? "/webgl.png" : "/webgl-off.png");
    document.getElementById('webgl_logo_wrapper').appendChild(glicon);

    // 브라우저가 사진 Orientation 보정을 자동으로 지원하지는지 확인
    testImg = new Image();
    testImg.onload = function () {
        supportImageOrientation = testImg.width === 2 && testImg.height === 3;
    };
    testImg.src =
      'data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAA' +
      'AAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA' +
      'QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE' +
      'BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAIAAwMBEQACEQEDEQH/x' +
      'ABRAAEAAAAAAAAAAAAAAAAAAAAKEAEBAQADAQEAAAAAAAAAAAAGBQQDCAkCBwEBAAAAAAA' +
      'AAAAAAAAAAAAAABEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AG8T9NfSMEVMhQ' +
      'voP3fFiRZ+MTHDifa/95OFSZU5OzRzxkyejv8ciEfhSceSXGjS8eSdLnZc2HDm4M3BxcXw' +
      'H/9k=';
}
