Ext.ns('Tsf.site');

Tsf.site.Slides = Ext.extend(Ext.util.Observable, {
    // Config
    wrap: true,
    selector: '.step',
    historyName: 'step',
    tokenDelimiter: ':',
    

    constructor: function(elId, config) {
        config = config || {};
        Ext.apply(this, config);

        Tsf.site.Slides.superclass.constructor.call(this, config);
        
        this.el = Ext.get(elId);
        
        this.initModel();
        this.initMarkup();
        this.initEvents();
        if (config.useHistory) {
            this.initHistory();
        }
        
        if (!config.useHistory && this.initialStep) {
            this.setStep(this.getIndexFromModel(this.initialStep));
        }
    },
    
    initMarkup: function() {
        // this.stageImage = Ext.get('stage-image').hide();
        this.stageImage = Ext.get('stage-image');
        
        // Setup stage
        // var stageClassNames = 'step ' + this.initialStep;
        var stageClassNames = 'step ';
        this.stage = this.el.child('.steps').insertFirst(this.el.child(this.selector, true)
            .cloneNode(true))
                .show()
                .set({
                    id: 'slide-stage',
                    "class": stageClassNames
                });
    },
    
    initModel: function() {
        this.model = {};
        this.model.items = [];
        // Store record indexes by name, useful for history
        this.model.indices = {};
        
        var cnt = 0;
        var items = this.el.select(this.selector).each(function(el) {
            var item = el;
            this.add(item, cnt);
            cnt++;
        }, this);
    },
    
    // Abstract method, implement your events
    initEvents: function() {},
    
    initHistory: function() {
        Ext.History.init();

        var bookmarkedState = Ext.History.getToken();
        if (bookmarkedState) {
            bookmarkedState = bookmarkedState.split(this.tokenDelimiter)[1];
        }
        this.initialStep = bookmarkedState || this.initialStep;
        if (!this.initialStep) {
            throw('You must pass an initial step when using History.');
        }

        var index = this.getIndexFromModel(this.initialStep);
        if (index == undefined) index = 0;
        Ext.History.on('change', this.onHistoryChange, this);
        Ext.History.add(this.historyName + this.tokenDelimiter + this.initialStep);
        this.setDocumentTitle(index);
        this.setStep(index);
    },
    
    // Abstract method, implement a change handler
    onHistoryChange: function(token) {},
    
    setStep: function(index) {
        if (this.wrap && (index == this.model.items.length || index < 0)) {
            if (index < 0) {
                index = this.model.items.length-1;
            } else {
                index = 0;
            }
        }
        this.activeIndex = index;
        var data = this.model.items[index];
        if (!data) {
            // Use the first item if no data was found.
            Ext.History.add(this.historyName + this.tokenDelimiter + this.initialStep   );
            return;
        }
        this.activeStep = data;
        
        if (this.trackViews) this.trackView();
        this.stageImage.hide();
        this.setupStage(data);
        this.animateStage();
    },

    // animateStage: function() {
    //     this.stageImage.show({duration: 0.75});
    // },
    
    trackView: function() {},
    
    // Show the stage after the first image has loaded
    animateStage: function() {
        var firstImage = this.stageImage.child('img.scene');
        if (firstImage.dom.complete) {
            this.stageImage.show({duration: 0.75});
        } else {
            firstImage.on('load', function(evt, t) {
                this.stageImage.show({duration: 0.75});
            }, this, {single: true});
        }
    },
    
    // Abstract method, add item to the model
    // el is an Ext Element used as the model record
    add: function(el, index) {},
    
    // Abstract method, set the stage from model record
    setupStage: function(data) {},
    
    getIndexFromModel: function(bookmark) {
        return this.model.indices[bookmark]? this.model.indices[bookmark] : 0;
    },

    findRecordByName: function(name) {
        return this.model.items[this.model.indices[name]];
    },
    
    getImagePaths: function(els) {
        var imagePaths = [];
        els.each(function(el) {
            var image = el;
            imagePaths.push(image.getAttribute('src'));
            image.remove();
        });
        return imagePaths;
    },
        
    setDocumentTitle: function(index) {}
    
});
