/**
 * TensoMaker - Gerador de sequencias de imagens segundo o meme TENSO
 *
 * Copyright (c) 2009, Fabricio Zuardi
 * All rights reserved.
 *  
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *   * Neither the name of the author nor the names of its contributors
 *     may be used to endorse or promote products derived from this
 *     software without specific prior written permission.
 *  
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **/

imageWidth = 0
imageHeight = 0

function initUI(){
    $('begin-slider').setStyle('visibility', 'visible')
    $('begin-zoom-handler').setStyle('visibility', 'visible')
    $('begin-resize-handler').setStyle('visibility', 'visible')
    $('end-slider').setStyle('visibility', 'visible')
    $('end-zoom-handler').setStyle('visibility', 'visible')
    $('end-resize-handler').setStyle('visibility', 'visible')
    var beginImage  = $('begin-image')
    var endImage    = $('end-image')
    var endLabel    = $('end-label')
    var beginCrop = $('begin').makeResizable({
        'handle' : $('begin-resize-handler'),
        'onDrag' : resizeCrop
    });
    var endCrop = $('end').makeResizable({
        'handle' : $('end-resize-handler'),
        'onDrag' : resizeCrop
    });
    var beginImageDrag  = beginImage.makeDraggable({'onDrag' : imageDrag});
    var endImageDrag    = endImage.makeDraggable({'onDrag' : imageDrag});
    var endLabelDrag    = endLabel.makeDraggable({});
    beginImage.addEvent('mousedown', function(){this.setStyle('cursor','-moz-grabbing')})
    beginImage.addEvent('mouseup', function(){this.setStyle('cursor','move')})
    endImage.addEvent('mousedown', function(){this.setStyle('cursor','-moz-grabbing')})
    endImage.addEvent('mouseup', function(){this.setStyle('cursor','move')})
    endLabel.addEvent('mousedown', function(){this.setStyle('cursor','-moz-grabbing')})
    endLabel.addEvent('mouseup', function(){this.setStyle('cursor','move')})
    
    setupSliders()
}
function resizeCrop(div_element){
    var beginImage = $('begin-image')
    var beginImgX = beginImage.offsetLeft
    var beginImgY = beginImage.offsetTop
    var beginImgW = beginImage.offsetWidth
    var beginImgH = beginImage.offsetHeight
    var beginImgVisibleW = beginImgW+beginImgX
    var beginImgVisibleH = beginImgH+beginImgY
    var endImage = $('end-image')
    var endImgX = endImage.offsetLeft
    var endImgY = endImage.offsetTop
    var endImgW = endImage.offsetWidth
    var endImgH = endImage.clientHeight
    var endImgVisibleW = endImgW+endImgX
    var endImgVisibleH = endImgH+endImgY
    var newW = div_element.clientWidth
    var newH = div_element.clientHeight
    var maxW = Math.min(beginImgW,endImgW)+2
    var maxH = Math.min(beginImgH,endImgH)+2
    var endLabel = $('end-label')
    var endLabelText = $('end-text')
    var endLabelX = endLabel.offsetLeft
    var endLabelY = endLabel.offsetTop
    var endLabelW = endLabelText.offsetWidth
    var endLabelH = endLabelText.offsetHeight
    //limits
    if (newW > maxW) {
        newW = maxW
        div_element.set('styles',{'width': newW+'px'})
    }
    if (newH > maxH) {
        newH = maxH
        div_element.set('styles',{'height': newH+'px'})
    }
    var newContainerDimensions = {
        'width'  : (newW-2) + 'px',
        'height' : (newH-2) + 'px'
    }
    var newCropDimensions = {
        'width'  : newW + 'px',
        'height' : newH + 'px'
    }
    var newBeginImagePosition = {
        'left' : ((newW-2 > beginImgVisibleW) ? (newW-2-beginImgW) : (beginImgX))+'px',
        'top'  : ((newH-2 > beginImgVisibleH) ? (newH-2-beginImgH) : (beginImgY))+'px'
    }
    var newEndImagePosition = {
        'left' : ((newW-2 > endImgVisibleW) ? (newW-2-endImgW) : (endImgX))+'px',
        'top'  : ((newH-2 > endImgVisibleH) ? (newH-2-endImgH) : (endImgY))+'px'
    }
    var newEndLabelPosition = {
        'left' : ((newW-2 < endLabelX + endLabelW)  ? (newW-2-endLabelW)  : (endLabelX+1))+'px',
        'top'  : ((newH-2 < endLabelY  + endLabelH) ? (newH-2-endLabelH)  : (endLabelY+1))+'px'
    }
    $('begin').set('styles', newCropDimensions)
    $('end'  ).set('styles', newCropDimensions)
    $('begin-container').set('styles', newContainerDimensions)
    $('end-container'  ).set('styles', newContainerDimensions)
    endLabel.set('styles', newEndLabelPosition)
    beginImage.set('styles', newBeginImagePosition)
    endImage.set(  'styles', newEndImagePosition)
}
function resizeKeyframe(keyframe_name){
    var image = $(keyframe_name+'-image')
    var imageX = image.offsetLeft
    var imageY = image.offsetTop
    var imageW = image.offsetWidth
    var imageH = image.offsetHeight
    var visibleW = imageW+imageX
    var visibleH = imageH+imageY
    var container = $(keyframe_name+'-container')
    var crop = $(keyframe_name)
    var cropW = crop.clientWidth
    var cropH = crop.clientHeight
    var newCropDimensions = {
        'width'  : ((cropW-2 > visibleW) ? (visibleW+2) : (cropW))+'px',
        'height' : ((cropH-2 > visibleH) ? (visibleH+2) : (cropH))+'px'
    }
    var newContainerDimensions = {
        'width'  : ((cropW-2 > visibleW) ? (visibleW) : (cropW-2))+'px',
        'height' : ((cropH-2 > visibleH) ? (visibleH) : (cropH-2))+'px'
    }
    $('begin').set('styles', newCropDimensions)
    $('begin-container').set('styles', newContainerDimensions)
    $('end').set('styles', newCropDimensions)
    $('end-container').set('styles', newContainerDimensions)
}
function updateImageZoom(keyframe_name, scale){
    $(keyframe_name+'-image').set('styles',{
        'width' : Math.ceil(imageWidth * (scale/100)),
        'height' : Math.ceil(imageHeight * (scale/100))
    })
    $(keyframe_name+'-zoom-value').set('text', scale)
}
function setupSliders(){
    var beginSlider = new Slider('begin-slider', 'begin-zoom-handler', {
        range: [10, 600],
        wheel: false,
        snap: false,
        steps: 295,
        onStart: function(){
        },
        onChange: function(step){
            updateImageZoom('begin', step)
        },
        onComplete: function(){ 
            resizeKeyframe('begin')
         }
    });
    var endSlider = new Slider('end-slider', 'end-zoom-handler', {
        range: [10, 600],
        wheel: false,
        snap: false,
        steps: 295,
        onChange: function(step){
            updateImageZoom('end', step)
        },
        onComplete: function(){ resizeKeyframe('end') }
    });
    beginSlider.set(100)
    endSlider.set(100)
}
function imageDrag(img_element){
    var x = img_element.offsetLeft
    var y = img_element.offsetTop
    var containerW = img_element.parentNode.offsetWidth
    var containerH = img_element.parentNode.offsetHeight
    var imgW = Math.max(img_element.offsetWidth,containerW)
    var imgH = Math.max(img_element.offsetHeight,containerH)
    if (x > 0) { img_element.set('styles',{'left':'0px'})}
    if (y > 0) { img_element.set('styles',{'top':'0px'})}
    if (x < containerW-imgW) { img_element.set('styles',{'left':(containerW-imgW)+'px'})}
    if (y < containerH-imgH) { img_element.set('styles',{'top':(containerH-imgH)+'px'})}
}
function sourceURLKeyDown(event){
    if(event.key == 'enter'){
        var session_id = encodeURIComponent($('session-id').get('value'))
        var url = this.get('value')
        var cached_img_url = 'a/imageCache?key='+session_id+'&url='+encodeURIComponent(url)
        $('begin-image').set('src', "")
        $('end-image').set('src', "")
        $('begin-image').set('style', "")
        $('end-image').set('style', "")
        $('begin-image').set('src', cached_img_url)
        $('end-image').set('src', cached_img_url)
    }
}
function adjustKeyFrameSize(keyframe_image){
    var newW = keyframe_image.offsetWidth
    var newH = keyframe_image.offsetHeight
    var endLabel = $('end-label')
    var endLabelText = $('end-text')
    var labelW = endLabelText.offsetWidth
    var labelH = endLabelText.offsetHeight
    var newCropDimensions = {
        'width' : (newW+2)+'px',
        'height' : (newH+2)+'px'
    }
    var newContainerDimensions = {
        'width' : (newW) + 'px',
        'height' : (newH) + 'px'
    }
    var newEndLabelPosition = {
        'left' : (newW/2 - labelW/2) + 'px',
        'top' : (newH - labelH) + 'px',
    }
    $('begin').set('styles', newCropDimensions)
    $('end').set('styles', newCropDimensions)
    $('begin-container').set('styles', newContainerDimensions)
    $('end-container').set('styles', newContainerDimensions)
    $('begin-image').setStyle('visibility', 'visible')
    $('end-image').setStyle('visibility', 'visible')
    endLabel.set('styles', newEndLabelPosition)
}
function updateLabel(){
    var p_elements = $('end-label').getElements('p')
    var newText = $('tenso-label-field').get('value')
    for (var i=0; i<p_elements.length; i++){
        p_elements[i].set('text',newText)
    }
}
function updateLabelSize(label_id){
    var p_elements = $(label_id).getElements('p')
    var newSize = $('font-size-field').get('value')
    for (var i=0; i<p_elements.length; i++){
        p_elements[i].setStyle('font-size',newSize+'px')
    }
}
function drawCanvasText(){
    try{
        var canvas      = $('final-image')
        var ctx         = canvas.getContext('2d');
        var endLabel    = $('end-label')
        var p_elements  = endLabel.getElements('p')
        var font_size   = parseInt($('font-size-field').get('value'))
        var steps       = $('timeline-size-field').get('value')
        var crop        = $('begin')
        var text        = p_elements[0].get('text').toUpperCase()
        ctx.font = font_size + 'px "Impact", "Arial Black", Arial, sans-serif';
        for (var i=0; i<p_elements.length; i++){
            ctx.fillStyle   = "Black";
            ctx.textBaseline = "top"
            if(i==p_elements.length-1){
                ctx.fillStyle = "White";
            }
            ctx.fillText(   text, 
                            endLabel.offsetLeft + p_elements[i].offsetLeft,
                            (steps-1)*(crop.clientHeight-2) + endLabel.offsetTop + p_elements[i].offsetTop
                            );
        }
    }catch(e){
        alert('Seu navegador não possui os recursos necessários, Gera TENSO foi testado e funciona em Firefox 3.5 beta e Safari 4 beta.')
    }
}
function init(){
    createTextOutline('end-text');
    $('original-image-field').addEvent('keyup', sourceURLKeyDown, true)
    $('tenso-label-field').addEvent('keyup', updateLabel, true)
    $('font-size-field').addEvent('keyup', function(){updateLabelSize('end-label')}, true)
    $('begin-image').addEvent('load', function(){
        imageWidth = this.offsetWidth
        imageHeight = this.offsetHeight
        adjustKeyFrameSize(this)
        initUI()
    }, true)
    if ($('begin-image').offsetWidth > 80){
        imageWidth  = $('begin-image').offsetWidth
        imageHeight = $('begin-image').offsetHeight
        adjustKeyFrameSize($('begin-image'))
        initUI()
    }
}
function createTextOutline(text_id){
    var p_element = $(text_id)
    var outlines = ['n','ne','e','se','s','sw','w','nw']
    for (var i=0; i<outlines.length; i++){
        var new_p = new Element('p', {
            'class' : 'outline outline-'+outlines[i],
            'text' : p_element.get('text')
        })
        new_p.inject(p_element, 'before');
    }
}
function SwitchMode(mode){
    $('editor').setStyle('display', mode=='preview'?'none':'block')
    $('preview').setStyle('display', mode=='preview'?'block':'none')
}
function updatePreview(){
    var canvas      = $('final-image')
    var first       = $('begin')
    var last        = $('end')
    var firstImage  = $('begin-image')
    var lastImage   = $('end-image')
    var steps       = $('timeline-size-field').get('value')
    var preview     = $('previa')
    var src         = firstImage.get('src')
    var endLabel    = $('end-label')
    var text        = $('end-text').get('text')
    var frameW      = first.clientWidth-2
    var frameH      = first.clientHeight-2
    preview.set('html','');
    prepareCanvas()
    try{
        var ctx         = canvas.getContext('2d');
    }catch(e){
        alert('Seu navegador não possui os recursos necessários, Gera TENSO foi testado e funciona em Firefox 3.5 beta e Safari 4 beta.')
    }
    var previewContainer = new Element('div',{'id':'tenso-preview','styles':{'width':frameW+'px'}})
    for (var step=0;step<steps;step++){
        var dl = (lastImage.offsetLeft   - firstImage.offsetLeft)
        var dt = (lastImage.offsetTop    - firstImage.offsetTop)
        var dw = (lastImage.offsetWidth  - firstImage.offsetWidth)
        var dh = (lastImage.offsetHeight - firstImage.offsetHeight)
        var l = firstImage.offsetLeft + step*(dl/(steps-1))
        var t = firstImage.offsetTop + step*(dt/(steps-1)) 
        var w = firstImage.offsetWidth + step*(dw/(steps-1)) 
        var h = firstImage.offsetHeight + step*(dh/(steps-1)) 
        var containerStyle = 'width: '+(frameW)+'px; height: '+(frameH)+'px;'
        var imgStyle = 'width: '+w+'px; height: '+h+'px; left: '+l+'px; top: '+t+'px;'
        var labelStyle = 'left: '+endLabel.offsetLeft+'px; top: '+endLabel.offsetTop+'px;'
        var frameHTML = '<div class="image-container" style="'+containerStyle+'"><img src="'+src+'" style="'+imgStyle+'" alt="" /></div>'
        if(step == steps-1){
            frameHTML += '<div id="preview-end-label" class="lol-text-label" style="'+labelStyle+'"><p id="preview-end-text">'+text+'</p></div>'
        }
        var frame = new Element('div', {
            'class' : 'frame',
            'styles' : {
                'width'  : frameW+'px',
                'height' : frameH+'px'
            },
            'html' : frameHTML
        })
        frame.inject(previewContainer);
        //draw on the final image canvas
        try{
            var scale   = w/imageWidth
            var sx      = -(l/scale)
            var sy      = -(t/scale)
            var sWidth  = (frameW/scale)
            var sHeight = (frameH/scale)
            var dx      = 0
            var dy      = frameH * step
            var dWidth  = frameW
            var dHeight = frameH
            ctx.drawImage(firstImage, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
        }catch(e){
            alert('Seu navegador não possui os recursos necessários, Gera TENSO foi testado e funciona em Firefox 3.5 beta e Safari 4 beta.')
        }
    }
    previewContainer.inject(preview);
    createTextOutline('preview-end-text')
    updateLabelSize('preview-end-label')
    drawCanvasText()
    SwitchMode('preview')
}

function prepareCanvas(){
    try{
        var canvas  = $('final-image')
        var steps   = $('timeline-size-field').get('value')
        var img     = $('begin-image')
        var crop    = $('begin')
        var canvasW = crop.clientWidth
        var canvasH = steps * crop.clientHeight
        canvas.set('width', canvasW)
        canvas.set('height', canvasH)
        canvas.getContext('2d').clearRect(0, 0, canvasW, canvasH);
    }catch(e){
        alert('Seu navegador não possui os recursos necessários, Gera TENSO foi testado e funciona em Firefox 3.5 beta e Safari 4 beta.')
    }
}
function openFinalImage(type){
    var canvas  = $('final-image')
    var window_name = '_blank'
    // var popup_window = window.open(canvas.toDataURL(),window_name, 'scrollbars=yes,width='+canvas.get('width')+',height='+canvas.get('height'));
    var popup_window = window.open(canvas.toDataURL(type), '_blank');
    popup_window.focus()
    return false
}

function updateURLHash(){
    var frameW
    var frameH
    var firstX
    var firstY
    var firstScale
    var lastX
    var lastY
    var lastScale
    var fontSize
    var textX
    var textY
    var text
    var hash =  '#w='  +frameW+
                ',h='  +frameH+
                ',x0=' +firstX+
                ',y0=' +firstY+
                ',z0=' +firstScale+
                ',x='  +lastX+
                ',y='  +lastY+
                ',z='  +lastScale+
                ',ts=' +fontSize+
                ',tx=' +textX+
                ',ty=' +textY+
                ',t='  +text
}
window.addEvent('domready', init);