
var OTOS = window.OTOS || {};
OTOS.Camera = function () {

    return {

        /**
         * An object containing all the graphics object generated in the page
         */
        GRAPH_OBJECTS: {},


        /**
         * The original width of the camera image
         */
        ORIGINAL_WIDTH: null,


        /**
         * The timer which updates the camera images at a certain interval
         */
        TIMER: null,


        /**
         * The size of the image compared to it's original size
         */
        IMAGE_FACTOR: null,


        /**
         * Shows only one camera and it's statistics.
         *
         * @param   {string}    serverAddress   The address of the server
         * @param   {string}    camId           The id of the camera
         */
        showCameraAndStatistics: function (serverAddress, camId) {
            var newCamera = new Camera(serverAddress, camId, false, $(CONTENT_ELEMENT_ID));
            newCamera.show();
        },


        /**
         * Creates or removes the chosen cameraInfo -element
         *
         * @param   {String}        serverAddress   The address of the server
         * @param   {String}        camId           The id of the camera
         * @param   {boolean}       update          Whether to update the window.location.hash or not
         */
        cameraInfo: function (serverAddress, camId, update) {

            var newCamera = new Camera(serverAddress, camId, false, $(CONTENT_ELEMENT_ID));
            newCamera.showInfo();

            if (update) {
                OTOS.Main.updateHash();
            } // if

        },


        /**
         * Shows only the view-mode of the camera, ie. only the image element and it's header
         *
         * @param   {String}    serverAddress   The ip address of the server
         * @param   {String}    camId           The camera's id
         */
        cameraView: function (serverAddress, camId) {
            var newCamera = new Camera(serverAddress, camId, false, $(CONTENT_ELEMENT_ID));
            newCamera.showImage();
        },


        /**
         * Updates the camera images in the page. Gets the information
         * from the database with Ajax and sends the response to the handler
         * function. The function starts a timer, which calls this function
         * every once in a while (the delay is the second argument of the
         * setTimeout-function in milliseconds)
         */
        updateCameraImages: function () {

            if (document.getElementsByClassName('imageContainer', $(CONTENT_ELEMENT_ID)).length > 0) {

                var myAjax  = new Ajax.Request(
                        'xmlHttpFunctions.php', {
                            method: 'get',
                            parameters: 'getAllImages=1',
                            onSuccess: function (request) { OTOS.Camera.handleImageUpdate(request) },
                            asynchronous: true
                        });

                OTOS.Camera.TIMER = setTimeout("OTOS.Camera.updateCameraImages()", 10000);

            } // if

        },


        /**
         * The handler of the xmlHttp request, which gets information of all the images from
         * the database. Creates the image if tit doesn't exist and updates it otherwise.
         * Creates/updates also the 'updated'-text underneath the image
         *
         * @param   {object}   request         The XmlHttp-request
         */
        handleImageUpdate: function (request) {

            var imageArr = request.responseText.split('#');

            // go through all the images

            for (var j = 0; j < imageArr.length; j++) {

                var imageInfo       = imageArr[j].split('|'), // explode the information into an array
                    camId           = imageInfo[4],
                    serverAddress   = imageInfo[5],
                    showImage       = imageInfo[6],
                    parentEl        = $('imageContainer' + '_' + serverAddress + '_' + camId);

                // if the image is in the database, but should not be in the page, we'll skip the rest of the loop
                if (parentEl == undefined) {
                    continue;
                } // if

                var imageDate = new Date(imageInfo[1] * 1000),
                    imageText = 'Päivitetty ' + imageDate.formatDate('d.m.Y H:i:s');

                // if the canvas doesn't exist yet, let's create it

                if ($('canvasContainer_' + camId) == undefined) {

                    var imageWidth  = OTOS.ElementManager.getImageWidth(),
                        factor      = imageInfo[3] / imageInfo[2],
                        imageHeight = imageWidth * factor;

                    OTOS.Camera.ORIGINAL_WIDTH  = imageInfo[2];
                    OTOS.Camera.IMAGE_FACTOR    = imageWidth / OTOS.Camera.ORIGINAL_WIDTH;

                    /*
                    * create the areaLinks, image element and the text. the canvas
                    * element has to have width and height attributes to get the damn
                    * thing to work with Internet Explorer + the style-attribute just to
                    * get it work. the element is too wide if the style-attribute with
                    * the size isn't set.
                    */
                    var canvasContainer = Builder.node('div', {
                            id: 'canvasContainer_' + camId,
                            className: 'canvasContainer'
                        }, [
                            Builder.node('img', {
                                id: 'canvasBg_' + camId,
                                src: imageInfo[0] + '?' + Date.parse(new Date()),
                                width: '100%',
                                height: '100%'
                            }),
                            Builder.node('div', {
                                id: 'canvas_' + camId,
                                className: 'canvas',
                                style: 'width: 100%; height: 100%'
                            })
                        ]);

                    canvasContainer.style.width  = parseInt(imageWidth) + 'px';
                    canvasContainer.style.height = parseInt(imageHeight) + 'px';

                    parentEl.appendChild(canvasContainer);

                    if (showImage == 0) {
                        canvasContainer.appendChild(OTOS.Camera.showCameraMask(camId));
                    } // if

                    parentEl.appendChild(Builder.node('p', { className: 'imageText' }, [document.createTextNode(imageText)]));

                    OTOS.Camera.GRAPH_OBJECTS[camId] = new jsGraphics('canvas_' + camId); // new graphics object
                    parentEl.appendChild(OTOS.Camera.createAreaLinks(serverAddress,
                                                                     camId,
                                                                     OTOS.Camera.IMAGE_FACTOR,
                                                                     OTOS.Camera.GRAPH_OBJECTS[camId]));

                    OTOS.ElementManager.setCameraBarHeights((OTOS.Main && OTOS.Main.TREEMODE)
                        ? OTOS.Dom.getFirstAncestorByClassName(parentEl, 'cameraRowContainer')
                        : $(CONTENT_ELEMENT_ID));

                // the canvas exists, let's update the image source + the text underneath it

                } else {

                    var imgEl   = $('canvasBg_' + camId),
                        imgUrl  = imgEl.getAttribute('src').split('?')[0] + '?' + Date.parse(new Date());

                    imgEl.setAttribute('src', imgUrl);
                    $('canvasContainer_' + camId).nextSibling.firstChild.nodeValue = imageText;

                    if (showImage == 0 && ($('imageMask_' + camId) == undefined)) {
                        $('canvasContainer_' + camId).appendChild(OTOS.Camera.showCameraMask(camId));
                    } else if (showImage == 1 && ($('imageMask_' + camId) != undefined)) {
                        Element.remove($('imageMask_' + camId));
                    } // else if

                } // else

            } // for

        },


        /**
         * Creates a mask element that can be placed over the camera image when the
         * updating of the image is disabled.
         *
         * @param   {String}     camId   The id of the camera
         * @return  The image mask -element
         * @type    {element}
         */
        showCameraMask: function (camId) {
            return Builder.node('div', {
                        id: 'imageMask_' + camId,
                        className: 'imageMask',
                        style: 'width: 100%; height: 100%;'
                    }, [
                        Builder.node('img', {
                            src: 'images/imagemask.gif',
                            height: '100%',
                            width: '100%'
                        })
                    ]);
        },


        /**
         * Updates the sizes of every camera image, re-creates the graph-object of the
         * corresponding camera and re-creates the image area links (names). The links and the graph
         * object have to be changed, because the image size is changed and the areas don't
         * show up correctly.
         */
        updateImageSizes: function () {

            var elementContent  = $(CONTENT_ELEMENT_ID),
                containers      = document.getElementsByClassName('canvasContainer', elementContent);

            for (var i = 0; i < containers.length; i++) {

                var cont            = containers[i],
                    origWidth       = parseInt(cont.style.width),
                    factor          = parseInt(cont.style.height) / origWidth,
                    width           = OTOS.ElementManager.getImageWidth(),
                    height          = parseInt(width * factor),
                    serverAddress   = cont.parentNode.id.split('_')[1],
                    camId           = cont.parentNode.id.split('_')[2];

                cont.style.width   = width + 'px';
                cont.style.height  = height + 'px';

                OTOS.Camera.IMAGE_FACTOR            = width / OTOS.Camera.ORIGINAL_WIDTH;
                OTOS.Camera.GRAPH_OBJECTS[camId]    = new jsGraphics('canvas_' + camId);

                // re-create the area links
                Element.remove(cont.parentNode.lastChild);
                var areaLinks = OTOS.Camera.createAreaLinks(serverAddress, camId, OTOS.Camera.IMAGE_FACTOR);
                cont.parentNode.appendChild(areaLinks);

            } // for

        },


        /**
         * Creates the mouseover event for the element brought as an argument. When the
         * mouse is over the element, the image area with the coordinates (in arguments)
         * is drawn to the graphics object (in arguments also).
         *
         * @param   {element}       el          The element to attach the event to
         * @param   {String}        coords      The area coordinates
         * @param   {double}        factor      The area size factor
         * @param   {jsGraphics}    graphObj    The graphics object
         */
        myDrawArea: function (el, coords, factor, graphObj) {

            coords = coords.split(',');

            function mouseoverHandler(e) {
                OTOS.Graphics.drawArea(coords, factor, graphObj, false);
            }

            Event.stopObserving(el, 'mouseover', mouseoverHandler);
            Event.observe(el, 'mouseover', mouseoverHandler);

        },


        /**
         * Creates the mouseout event for the element brought as an argument, that
         * clears the graphics object (or the canvas in fact).
         *
         * @param   {element}       el          The element to attach the event to
         * @param   {jsGraphics}    graphObj    The graphics object
         */
        myClearArea: function (el, graphObj) {

            function mouseoutHandler(e) {
                OTOS.Graphics.clearCanvas(graphObj);
            }

            Event.stopObserving(el, 'mouseout', mouseoutHandler);
            Event.observe(el, 'mouseout', mouseoutHandler);

        },


        /**
         * Creates and returns a paragraph with the area names in it. Each name has mouseout- and mouseover-
         * event handlers attached to them, so when the mouse is hovered over the name,
         * the corresponding area is shown in the canvas.
         *
         * @param   {String}    serverAddress   The address of the server
         * @param   {String}    camId           The id of the camera
         * @param   {double}    factor          Current image size compared to the original
         * @return  A paragraph element with the area names
         * @type    {element}
         */
        createAreaLinks: function (serverAddress, camId, factor) {

            var counter     = 0,
                areaLinks   = Builder.node('p', { className: 'areaLinks' }, [
                                Builder.node('strong', 'Laskenta-alueet', ': ')]),
                areas       = OTOS.ElementConfig.SERVERDATA[serverAddress]['cameras'][camId]['imageAreas'];

            // go through the camera's areas and append the names into the element

            for (var i in areas) {

                var linkElement = Builder.node('span', { className: 'areaLink' }, areas[i]['name']);
                var coords = areas[i]['coords'];

                // attach the event handlers
                OTOS.Camera.myDrawArea(linkElement, coords, factor, OTOS.Camera.GRAPH_OBJECTS[camId]);
                OTOS.Camera.myClearArea(linkElement, OTOS.Camera.GRAPH_OBJECTS[camId]);

                if (counter > 0) {
                    areaLinks.appendChild(document.createTextNode(', '));
                } // if

                areaLinks.appendChild(linkElement);
                counter++;

            } // for

            return areaLinks;

        }

    };

}();
