
var SlidingBuilderAutomated = Class.create({
/**
    *  @constructor
    *       @param  images {hash} => images for sliding:
    *               { id, url, in_new_window, (optional) link, (optional) title, (optional), subtitle (optional), url_to_preview (optional) }
    *       @param  imageContainer      => html element that contains all the images
    *       @param  choiceContainer     => html element that contains the direct choose of all images (optional)
    *       @param  divImageInformation => html element that contains the current image information (optional)
    *       @param  imageSet            => how the images must be sorted (sliding || fading), default => sliding
    *       @param  linearSliding       => how the images must be showed by their order (true | false) default true
    *       @param  scrollForSlice:     => integer for the movement of imageContainer (necesary if image set = "sliding")
    *       @param  durationOfEffect:   => duration of effect sliding che fading
    *       @param  intervalTime:       => interval time of call for the effect
    */

  initialize: function(options){
      this.slidingContainer = new SlidingContainer({
        imageContainer:      options.imageContainer,
        htmlForText:         options.htmlForText ? options.htmlForText : 0,
        allTheImages:        options.allTheImages,
        imageSet:             options.imageSet,
        effectForSliding:   options.effectForSliding,
        imagesHasPreview:    options.imagesHasPreview,
        choiceContainer:     options.choiceContainer,
        divImageInformation: options.divImageInformation,
        image_preview: options.image_preview
      })
      
      this.slidingContainer.build()
      this.effectSliding = new EffectSliding({
         objectSlidingContainer:  this.slidingContainer,
         imageContainer:    options.imageContainer,
         effectMovement:    options.effectMovement,
         effectFading:      options.effectFading,
         directionOfEffect: options.directionOfEffect,
         scrollForSlice:    options.scrollForSlice ? options.scrollForSlice : $$('.imageTeaser')[0].scrollWidth, //options.scrollForSlice,
         imageSet:          options.imageSet
      })
      this.chrono = new Chrono({
        effectObject: this.effectSliding,
        image_has_preview: options.image_preview,
        imageSet: options.imageSet,
        slidingContainer: this.slidingContainer,
        nrOfSlice: options.imageContainer.children.length,
        durationOfEffect:  options.durationOfEffect,
        divImageInformation: options.divImageInformation ? true : false,
        intervalTime: options.intervalTime //ever second (default)
      })
  },
  build: function(){//qui chiamo in seguito le istanze dove chiedo di costruirsi
       this.chrono.checkLoadedImages()
       this.chrono.start() //chiedo a crhono di gestire tutti gli eventi
       this.slidingContainer.imageContainer.style.right = "0px"
  }
})

var SlidingContainer = Class.create({ //BUILD HTML ELEMENTS AND BIND THE EVENTS
   initialize: function (options) {
       this.allTheImages = options.allTheImages
       this.imageContainer = options.imageContainer // i think it will be always :D
       this.originalLenght = this.allTheImages.size()
       this.htmlForText = options.htmlForText
       this.imageSet = options.imageSet || "sliding"
       this.imageDimensions = options.imageDimension || null
       this.imagePreview = options.image_preview
       /*  over there only the optional configuration  */
       this.effectForSliding = options.effectForSliding || "scroll"
       options.imagesHasPreview ? this.imagesHasPreview = true : this.imagesHasPreview = false
       options.choiceContainer ? this.choiceContainer = options.choiceContainer : this.choiceContainer = null //if the images have direct choice
       options.divImageInformation ? this.divImageInformation = options.divImageInformation : this.divImageInformation = null /*if the images has a div for their information*/
   },
   emptyFunction: function(){

   },
   build: function(options){ //will be passed here the elements for the sliding effect, only if html elements are ready otherwise we must build it
       this.buildSlidingImage()
       this.choiceContainer ? this.buildDirectChoiceElement() : null
       this.divImageInformation ? this.buildDivImageInformation() : null
   },
   buildSlidingImage:function(){
       this.imageContainer.insert({
            bottom: this.htmlForElements()
       })
   },
   insertSlidingImage: function(){
       this.buildSlidingImage()
   },
   removeOldsSlice: function(){
       var i = 0
       while(i < this.originalLength){
           delete this.imageContainer.children[i]
           i++
       }
   },
   buildDirectChoiceElement:function(){
       this.choiceContainer.insert({
           bottom: this.htmlForDirectChoiceElement()
       })
   },
   buildDivImageInformation: function(){
       this.divImageInformation.insert({
           bottom: '<span class="title"></span><span class="subTitle"></span>'
       })
   },
   getStyleForImage: function(show){
        if(this.imageSet == "fading"){
            if(show){ /*height:310px; width:560px;*/
                return "position:absolute;  -moz-opacity: 0; -khtml-opacity: 0; opacity:1; filter:alpha(opacity=1);"}
            return "position:absolute; -moz-opacity: 0 -khtml-opacity: 0; opacity:0; filter:alpha(opacity=0);display:none;"
        }else if(this.imageSet == "sliding"){
            return "position:relative; float:left; margin:0px;"
        }
        return null
   },
   htmlForElements: function(){
       var htmlForAllImages = ''
       var htmlForSingleImage = ''
       if(!this.htmlForText){
           for(var i = 0; i < this.allTheImages.size(); i++){
               htmlForAllImages += '<a id=\"image_'+this.allTheImages[i].id+'\" class=\"imageTeaser\" style=\"'+this.getStyleForImage( (i == 0) ? true : false)+'\" '
               this.allTheImages[i].in_new_window ? htmlForSingleImage += ' target=\"_blank\"' : htmlForSingleImage += ''
               this.allTheImages[i].link ? htmlForSingleImage += ' href=\"'+this.allTheImages[i].link+'\">' : htmlForSingleImage += '>'
               this.allTheImages[i].url ? htmlForSingleImage += '<img class=\"imageTeaser\" src=\"'+this.allTheImages[i].url+'\" ' : htmlForSingleImage += ''
               this.allTheImages[i].title ? htmlForSingleImage += ' alt=\"'+this.allTheImages[i].title+'\"/>' : htmlForSingleImage += '>'
               htmlForAllImages = htmlForAllImages + htmlForSingleImage + '</a>'
               htmlForSingleImage = ""
           }
           if(this.imageSet == "sliding"){
               htmlForAllImages += '<a id=\"image_'+this.allTheImages[0].id+' clone\" class=\"\" style=\"'+this.getStyleForImage( (i == 0) ? true : false)+'\" '
               this.allTheImages[0].in_new_window ? htmlForSingleImage += ' target=\"_blank\"' : htmlForSingleImage += ''
               this.allTheImages[0].link ? htmlForSingleImage += ' href=\"'+this.allTheImages[0].link+'\">' : htmlForSingleImage += '>'
               this.allTheImages[0].url ? htmlForSingleImage += '<img class=\"imageTeaser\" src=\"'+this.allTheImages[0].url+'\" ' : htmlForSingleImage += ''
               this.allTheImages[0].title ? htmlForSingleImage += ' alt=\"'+this.allTheImages[0].title+'\"/>' : htmlForSingleImage += '>'
               htmlForAllImages = htmlForAllImages + htmlForSingleImage + '</a>'
               htmlForSingleImage = ""
           }
       }else{
            for( i = 0; i < this.allTheImages.size(); i++){
               htmlForAllImages += '<div id=\"image_'+this.allTheImages[i].id+'\" class=\"imageTeaser textTeaser\" style=\"'+this.getStyleForImage( (i == 0) ? true : false)+'\"><span class=\"internalText\" style=\"font-size:18px;\">'
                                                +this.allTheImages[i].text+
                                       '</span></div>'+this.allTheImages[i].link
           }
           if(this.imageSet == "sliding"){
               htmlForAllImages += '<div id=\"image_'+this.allTheImages[0].id+' clone\" class=\"imageTeaser textTeaser\" style=\"'+this.getStyleForImage( (i == 0) ? true : false)+'\"><span class=\"internalText\" style=\"font-size:18px;\">'
                                                +this.allTheImages[0].text+
                                       '</span></div>'+this.allTheImages[0].link
           }
       }
       return htmlForAllImages
   },
   htmlForDirectChoiceElement: function(){
       var htmlForAllDirectChoice = ''
       var htmlForSingleElement = ''
       for(var i = 0; i < this.allTheImages.size(); i++){
           if(this.imagePreview){
               htmlForSingleElement = '<div class=\"singleDirectChoice direct_choice_'+this.allTheImages[i].id+'\">'
               this.allTheImages[i].url_to_preview ?  htmlForSingleElement += '<img src=\"'+this.allTheImages[i].url_to_preview+'\" style=\"width:100%;height:100%\" alt=\"'+this.allTheImages[i].title+'\" />' : htmlForSingleElement += '<img src=\"'+this.allTheImages[i].url+'\" style=\"width:100%;height:100%\" alt=\"'+this.allTheImages[i].title+'\" />' //: ==> TO DO
               htmlForAllDirectChoice = htmlForAllDirectChoice + htmlForSingleElement + '</div>'
           }else{
               htmlForSingleElement = '<button class=\"singleDirectChoice direct_choice_'+this.allTheImages[i].id+'\">'
               htmlForAllDirectChoice = htmlForAllDirectChoice + htmlForSingleElement + '</button>'
           }
       }
       return htmlForAllDirectChoice
   },
   insertImageInformation: function(nrSlice){ /*   verra chiamata solo quando l'immagine cambia   */
       this.divImageInformation.children[0].innerHTML = this.allTheImages[nrSlice].title
       this.divImageInformation.children[1].innerHTML = this.allTheImages[nrSlice].subtitle
   },
   insertImage: function(){
       this.imageContainer.style.right = "0px"
       this.imageContainer.update(
            this.htmlForElements()
       )
   },
   setOpacityForElement: function(sliceElement){
       sliceElement.show()
       sliceElement.style.opacity = "opacity:0.0"
       sliceElement.style.filter = "alpha(opacity=0.0)"
       sliceElement.style.MozOpacity = 0;
       sliceElement.style.KhtmlOpacity = 0;
   }
});

var Chrono = Class.create({ //SEND THE INTERVAL TIME, IF PREVISTO, OF SLIDING EFFECT
    initialize: function(options){
        this.effectObject = options.effectObject
        this.intervalTime = options.intervalTime || 1
        this.durationOfEffect =  options.durationOfEffect,
        this.slidingContainerObject = options.slidingContainer;
        this.nrOfSlice = options.nrOfSlice
        this.directChoose = this.slidingContainerObject.choiceContainer
        this.imageHasPreview = options.image_has_preview
        this.divImageInformation = options.divImageInformation ? true : false
        this.prevSlice = 0
        this.imageSet = options.imageSet
        this.currentSlice = 0
        this.nextSlice = 1
        this.linearSliding = options.linearSliding || true //set if the images must be showed sorted or random
        this.sliceChoosebyUser = false
        this.currentPeriodicalExecuter = 0
        this.periodicalExecuter = []
        this.periodicalExecuterForClick = null
        this.i = 0
    },
    deleteLoadSpinner: function(){
        if($$('.imagesList')[0] != null){
           if($$('.teaser_preload_spinner').size())
               $$('.teaser_preload_spinner')[0].hide()
           this.periodicalExecuterForClick.stop()
        }
    },
    checkLoadedImages: function(){
      this.periodicalExecuterForClick = new PeriodicalExecuter(this.deleteLoadSpinner.bind(this), 0.1);
    },
    start: function(){
        this.effectObject.update(this)
        this.showSlideInformation() //for the first information
        this.setImageStausForDirectChoose() //for the first information
        this.directChoose ? this.bindDirectChoose({all: true}) : null
        this.periodicalExecuter[this.currentPeriodicalExecuter] = new PeriodicalExecuter(this.callSlidingObject.bind(this), this.intervalTime);
    },
   imgOver: function(window, element, isImg){
       if(isImg){
           element.style.borderWidth = '2px'
           element.style.borderStyle= 'solid'
           element.style.borderColor = '#f2e400'
       }else{
           element.style.backgroundColor = '#aaaaaa'
       }
   },
   imgOut: function(window, element, isImg){
       if(isImg){
           element.style.borderWidth = '2px'
           element.style.borderStyle= 'solid'
           element.style.borderColor = '#FFFFFF'
       }else{
           element.style.backgroundColor = '#2cbfde'
       }
   },
   bindDirectChoose: function(options){
       if(options.all){
           var i = 0
           var singleElement = null
           while(i < this.directChoose.children.length){
                singleElement = this.directChoose.children[i]
                Event.observe(singleElement,'mouseover', this.imgOver.bindAsEventListener(this,singleElement, this.imageHasPreview))
                Event.observe(singleElement,'mouseout' , this.imgOut.bindAsEventListener(this,singleElement, this.imageHasPreview))
                Event.observe(singleElement,'click'    , this.sliceChoose.bindAsEventListener(this,i))
                i++
           }
       }else{
           var singleElement = this.directChoose.children[options.idElement]
           singleElement.style.cursor = "pointer"
           Event.observe(singleElement,'mouseover', this.imgOver.bindAsEventListener(this,singleElement, this.imageHasPreview))
           Event.observe(singleElement,'mouseout' , this.imgOut.bindAsEventListener(this,singleElement, this.imageHasPreview))
           Event.observe(singleElement,'click'    , this.sliceChoose.bindAsEventListener(this,options.idElement))
       }
   },
   stopObserve: function(){
           var singleElement = this.directChoose.children[(this.currentSlice == this.nrOfSlice - 1) ? 0 : this.currentSlice]
           singleElement.style.cursor = ""
           Event.stopObserving( singleElement, 'mouseover')
           Event.stopObserving( singleElement, 'mouseout')
           Event.stopObserving( singleElement, 'click')
    },
    sliceChoose: function(window,elementChoose){
        if(elementChoose != this.currentSlice){
            this.nextSlice = elementChoose
            this.sliceChoosebyUser = true
            this.callEffectAfterClick()
        }
    },
    callEffectAfterClick: function(){
        if(this.effectIsFinished){
           this.periodicalExecuter[ this.currentPeriodicalExecuter].stop()
           this.callSlidingObject()
           this.currentPeriodicalExecuter++
           this.periodicalExecuter[ this.currentPeriodicalExecuter] = new PeriodicalExecuter(this.callSlidingObject.bind(this), this.intervalTime);
        }
    },
    effectFinished: function(){
        this.effectIsFinished = true
        this.showSlideInformation()
        this.setImageStausForDirectChoose()
    },
    setImageStausForDirectChoose: function(){
        if(this.directChoose){
            this.stopObserve()
            this.imgOut(  null, this.slidingContainerObject.choiceContainer.children[this.checkForSlideToPass(this.prevSlice)], this.imageHasPreview)
            this.imgOver( null, this.slidingContainerObject.choiceContainer.children[this.checkForSlideToPass(this.currentSlice)], this.imageHasPreview)
            this.bindDirectChoose({idElement: this.checkForSlideToPass(this.prevSlice)})
        }
    },
    showSlideInformation: function(){
        if(this.divImageInformation)
            this.slidingContainerObject.insertImageInformation(this.checkForSlideToPass(this.currentSlice))
    },
    stop: function(){
        this.periodicalExecuter.stop()
    },
    checkForSlideToPass: function(slide){
        if(this.imageSet == "fading")
            return slide
        else
            return (slide == this.nrOfSlice - 1) ? 0 : slide
    },
    callSlidingObject: function(){
        this.effectIsFinished = false
        this.effectObject.effect(this.currentSlice, this.nextSlice, this.durationOfEffect,0.2) //qui passo i parametri
        this.setSliceToShow()
        this.checkForResetStatus()
    },
    setSliceToShow: function(){
        this.prevSlice = this.currentSlice
        this.currentSlice = this.nextSlice;
        if(this.linearSliding) {
            if(this.sliceChoosebyUser){
                this.sliceChoosebyUser = false
                this.effectObject.setOpacityForElement($(this.slidingContainerObject.imageContainer.children[this.currentSlice].id))
            }
            this.nextSlice++;
        }else{
            this.nextSlice = this.getRandomNumber();
        }
    },
    getRandomNumber: function(){
        var random = this.nrOfSlice;
        while(random == this.currentSlice ){
              random = Math.floor( Math.random() % (this.nrOfSlice - 1 ) )
        }
        return random
    },
    checkForResetStatus: function(){
        if(this.nextSlice == this.nrOfSlice){
            if(this.imageSet =="fading") this.nextSlice = 0
            else this.nextSlice = 1
            this.effectObject.setOpacityForElement($(this.slidingContainerObject.imageContainer.children[this.currentSlice].id))
        }
    }
})

var EffectSliding = Class.create({
    initialize: function(options){
        this.sliceContainer = options.objectSlidingContainer.imageContainer //it can't be null
        this.numberOfSlice =  this.sliceContainer.children.length//why + 1?
        this.effectMovement = options.effectMovement || false
        this.effectFading = options.effectFading || false
        this.directionOfEffect = options.directionOfEffect || 'right'
        this.imageSet = options.imageSet
        this.objectSlidingContainer = options.objectSlidingContainer
        this.currentPosition = 0
        this.chrono = null
        this.effectFinished = 0
        this.scrollForSlice = options.scrollForSlice
        this.currentPage = this.currentPosition / this.scrollForSlice
    },
    update: function(object){
        this.chrono = object
    },
    effect: function(sliceToShow,nextSliceToShow,duration,delay){
        if(this.imageSet == "sliding"){
            this.morph(sliceToShow,nextSliceToShow,duration,delay)
        }else{
            this.fading(sliceToShow,nextSliceToShow,duration)
        }
    },
    fading: function(currentSlice,nextSlice,duration){
        var that = this
        var idCurrentSlice = this.sliceContainer.children[currentSlice].id
        var elementNextSlice = $(this.sliceContainer.children[nextSlice].id)
        this.setOpacityForElement(elementNextSlice)
        var currentImage = $(idCurrentSlice)
        var nextImage = $(elementNextSlice)
        currentImage.fade({
            duration: duration,from: 1,to: 0.0,afterFinish: function(){}
        })
        nextImage.fade({
            duration: duration,from: 0,to: 1.0,
            afterFinish: that.effectFinish.bind(that,currentSlice)
        })
    },
    effectFinish: function(){
      this.chrono.effectFinished()
    },
    setOpacityForElement: function(sliceElement){
        if(this.imageSet == "fading")
            this.objectSlidingContainer.setOpacityForElement(sliceElement)
    },
    morph: function(currentSlice, nextSlice,duration,delay){
        this.currentPosition  = this.scrollForSlice * nextSlice
        var that = this;
        this.objectSlidingContainer.imageContainer.morph(
                that.directionOfEffect +": " + this.currentPosition   + "px",{
                        duration: duration,
                        delay: 0,
                        afterFinish: function(){
                                that.checkPositionSlice(that.currentPosition,nextSlice);
                                that.effectFinish(that);
                                    }
                        }
        );
    },
    checkPositionSlice: function(currentPosition, nextSlice){
        if( currentPosition > 0 && ($(this.sliceContainer.children[nextSlice].id).id).split('clone')[1] != null ){
            this.objectSlidingContainer.insertImage() //dico al gestore dell'html di sistemarmi un nuovo pezzo di elementi.
            this.currentPosition = 0
        }
    },
    changeSliceAssets: function(){
        var i = 0
        var length = this.sliceContainer.children.length
        var sliceCloned = Object.clone(this.sliceContainer.children)
        while(i < this.sliceContainer.children.length-1){
            this.sliceContainer.children[i] = sliceCloned[length-1]
            length--;i++;
        }
        this.currentSlice = 1
        this.objectSlidingContainer.insertSlidingImage()
        this.objectSlidingContainer.removeOldsSlice()
    }
})
