define([
    "./button.builder",
    "jquery",
	"css!./picture-gallery.css"
],
function(
    ButtonBuilder,
    jq
){

    "use strict";

    /**
     * @constructor
     */

    return function(options, context, metadata){
        var container,
            wrapper,
            picture,
            currentPicture = 0,
            indicators = new Array(),
            backButton,
            nextButton;

        function hexToRgb(hex) {
            var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
            return result ? {
                r: parseInt(result[1], 16),
                g: parseInt(result[2], 16),
                b: parseInt(result[3], 16)
            } : {
                r: 0,
                g: 0,
                b: 0
            };
        }

        function asRgbaValue( colorValue, transparencyValue ) {

            var color = hexToRgb( colorValue ),
                alpha = asAlpha( transparencyValue );

            return "rgba(" + color.r + ", " + color.g + ", " + color.b + ", " + alpha + ")";
        }

        function asAlpha( percentValue ) {
            return (100 - percentValue) / 100;
        }

        function createPictureGallery() {

            var width = options.width,
                height = options.height,
                backgroundColor = options.backgroundColor,
                backgroundTransparency = options.backgroundTransparency,
                pictureBackgroundColor = options.pictureBackgroundColor,
                pictureBackgroundColorTransparency = options.pictureBackgroundColorTransparency,
                picturePadding = options.picturePadding,
                pictureHeight = options.picture[currentPicture].height,
                pictureWidth = options.picture[currentPicture].width,
                pictureParams = calculatePictureParams(pictureWidth, pictureHeight, picturePadding, height, width),
                optionsBack = options.controlImage.back,
                optionsNext = options.controlImage.next;

            wrapper = jq(document.createElement("div"))
                .attr({
                    "id" : "wrapper" + options.instanceId
                })
                .css({
                    "width" : pictureParams.width + (2 * picturePadding) + "px",
                    "height" : pictureParams.height + (2 * picturePadding) + "px",
                    "background-color" : asRgbaValue(pictureBackgroundColor, pictureBackgroundColorTransparency)
                });

            picture = jq(document.createElement("img"))
                .attr({
                    "id" : "picture" + options.instanceId,
                    "src" : options.picture[currentPicture].fileNameURL
                })
                .css({
                    "width" : pictureParams.width + "px",
                    "height" : pictureParams.heigth  + "px"
                });

            container = jq(document.createElement("div"))
                .attr({
                    "id" : "container" + options.instanceId
                })
                .css({
                    "background-color" : asRgbaValue(backgroundColor,backgroundTransparency)
                })
                .addClass("container");

            backButton = new ButtonBuilder({
                fileNameURL : optionsBack.fileNameURL, 
                width : optionsBack.width,
                height : optionsBack.height / 3,
                name : "backButton"}, context, metadata).build();
            nextButton = new ButtonBuilder({
                fileNameURL : optionsNext.fileNameURL,
                width : optionsNext.width,
                height : optionsNext.height / 3,
                name : "nextButton"}, context, metadata).build();

            wrapper.append(picture);
            picture.addClass("picture");
            container.append(wrapper);
            wrapper.addClass("wrapper");
            container.append(backButton.getElement());
            container.append(nextButton.getElement());
            container.append(createIndicatorArea());

            showImage(currentPicture);
        }

        function createIndicatorArea(){
            var indicatorArea = jq(document.createElement("div"))
                    .attr({
                        "id" : "indicatorArea" + options.instanceId
                    })
                    .css({
                        "padding-bottom" : options.indicatorPadding + "px"
                    })
                    .addClass("IndicatorArea");

            for (var i = 0; i < options.picture.length ; i++) {
                indicators.push(createIndicator(i));
                indicatorArea.append(indicators[i]);
            }

            return indicatorArea;
        }

        function createIndicator(number){
            return jq(document.createElement("div"))
                .attr({
                    "id" : "indicator" + number + options.instanceId
                })
                .css({
                    "background-color": options.indicatorColor,
                    "width" : options.indicatorSize + "px",
                    "height" : options.indicatorSize + "px",
                    "margin-bottom" : ((options.controlImage.next.height / 3) - options.indicatorSize) / 2 + "px"
                })
                .addClass("Indicator")
                .on(options.pointerEvents.pointerDown, function(e){
                    lockNavigation();
                    e.preventDefault();
                    e.stopPropagation();
                })
                .on(options.pointerEvents.pointerUp, function(e){
                    unlockNavigation();
                    e.preventDefault();
                    e.stopPropagation();
                    if(!isOnTarget(e)) {
                        return;
                    }
                    showImage(number);
                })
        }

        function calculatePictureParams(pictureWidth, pictureHeight, picturePadding, height, width){
            var result = new Array(),
                calculatedHeight,
                calculatedWidth;

            calculatedHeight = height - (2 * picturePadding);
            calculatedWidth = calculatedHeight * (pictureWidth / pictureHeight);

            if (calculatedWidth > width - (2 * picturePadding)){
                calculatedWidth = width - (2 * picturePadding);
                calculatedHeight = calculatedWidth * (pictureHeight / pictureWidth);
            }

            result.width = calculatedWidth;
            result.height = calculatedHeight;

            return result;
        }

        function showImage(image){
            var width = options.width,
                height = options.height,
                pictureHeight,
                pictureWidth,
                picturePadding = options.picturePadding,
                pictureParams;

            pictureHeight = options.picture[image].height;
            pictureWidth = options.picture[image].width;

            pictureParams = calculatePictureParams(pictureWidth, pictureHeight, picturePadding, height, width);

            wrapper
                .css({
                    "width" : pictureParams.width + (2 * picturePadding) + "px",
                    "height" : pictureParams.height + (2 * picturePadding) + "px"
                });

            picture
                .attr({
                    "src" : options.picture[image].fileNameURL
                })
                .css({
                    "width" : pictureParams.width + "px",
                    "height" : pictureParams.height  + "px"
                });

            indicators[currentPicture]
                .css({
                    "background-color": options.indicatorColor
                })
            indicators[image]
                .css({
                    "background-color": options.indicatorColorActive
                })
            currentPicture = image;
        }

        function isOnTarget(e) {

			var elem = e.target,
				origEvent = e.originalEvent,
				changedTouch = origEvent.changedTouches && origEvent.changedTouches.length > 0 ? origEvent.changedTouches[0] : undefined;

			if(changedTouch) {
				elem = document.elementFromPoint(changedTouch.clientX, changedTouch.clientY);
			}

			return e.target === elem;
        }

        function lockNavigation() {
            if (context.stage.isInAuthoringMode() || (typeof(context.stage.trigger) === "undefined")) {
                return;
            }
            context.stage.trigger.lock( metadata.getId() );
        }

        function unlockNavigation() {
            if (context.stage.isInAuthoringMode() || (typeof(context.stage.trigger) === "undefined")) {
                return;
            }
            context.stage.trigger.unlock( metadata.getId() );
        }

        return {
            build : function(){
                createPictureGallery();
                return{
                    getElement : function(){
                        return container.get(0);
                    },
                    getBackButton : function(){
                        return backButton;
                    },
                    getNextButton : function(){
                        return nextButton;
                    },
                    onBackMouseUp : function(e){
                        backButton.onMouseUp(e);

                        if(!isOnTarget(e)) {
                            return;
                        }

                        if(currentPicture > 0){
                            showImage(currentPicture - 1);
                        }else{
                            if((options.picture.length - 1) > 0){
                                showImage(options.picture.length - 1);
                            }else{
                                showImage(0);
                            }
                        }
                    },
                    onNextMouseUp : function(e){
                        nextButton.onMouseUp(e);

                        if(!isOnTarget(e)) {
                            return;
                        }

                        if(currentPicture < (options.picture.length - 1)){
                            showImage(currentPicture + 1);
                        }else{
                            showImage(0);
                        }
                    }
                }
            }
        }
    }
});