function SwitcherElement(id) {
    this.element = document.getElementById(id);
    this.width = 100;
    this.height = 100;
}

function SwitcherElementResize(width, height) {
    this.width = width;
    this.height = height;
    this.element.style.width = width + "px";
    this.element.style.height = height + "px";
}

function SwitcherElementMove(x, y) {
    this.x = x;
    this.y = y;
    this.element.style.left = x + "px";
    this.element.style.top = y + "px";
}

function SwitcherElementGetX() {
    return this.x;
}

function SwitcherElementGetY() {
    return this.y;
}

function SwitcherElementGetWidth() {
    return this.width;
}

function SwitcherElementGetHeight() {
    return this.height;
}

function SwitcherElementSetOpacity(opacity) {
    try {
        if (this.element.style.filter == null) throw new Exception();
        this.element.style.filter = "alpha(opacity=" + opacity + ")";
    }
    catch (e) {
        this.element.style.opacity = opacity / 100;
    }
}

SwitcherElement.prototype.resize = SwitcherElementResize;
SwitcherElement.prototype.getX = SwitcherElementGetX;
SwitcherElement.prototype.getY = SwitcherElementGetY;
SwitcherElement.prototype.getWidth = SwitcherElementGetWidth;
SwitcherElement.prototype.getHeight = SwitcherElementGetHeight;
SwitcherElement.prototype.setOpacity = SwitcherElementSetOpacity;
SwitcherElement.prototype.move = SwitcherElementMove;

function ScrolledSwitcher(ids, parentElement, params) {
    //Setting width and height of the elements
    
    if(params.length>0) {
    this.opacity = params['opacity'];
    this.smallWidth = params['smallWidth'];
    this.smallHeight = params['smallHeight'];
    this.bigWidth = params['bigWidth'];
    this.bigHeight = params['bigHeight'];
    this.viewWidth = params['viewWidth'];
    this.viewHeight = params['viewHeight'];
    this.spaceWidth = params['spaceWidth'];
    } else {
    this.opacity = 50;
    this.smallWidth = 87;
    this.smallHeight = 135;
    this.bigWidth = 114;
    this.bigHeight = 180;
    this.viewWidth = 400;
    this.viewHeight = 200;
    this.spaceWidth = 20;
    }

    this.parentElement = parentElement;
    this.elements = Array();
    this.focused = 0;
    this.oldFocused = null;
    for (var i = 0; i < ids.length; i++) {
        this.elements[i] = new SwitcherElement(ids[i]);
        if (i == this.focused) { //element 0 is focused at the beginning
            this.elements[i].resize(this.bigWidth, this.bigHeight);
            this.elements[i].setOpacity(100);
        }
        else {
            this.elements[i].resize(this.smallWidth, this.smallHeight);
            this.elements[i].setOpacity(this.opacity);
        }
        this.elements[i].move(-1 * (this.bigWidth * 2), 0);
    }
    this.draw(0, this.smallWidth + this.spaceWidth);

    this.oldScrollX = null;
    this.newScrollX = null;
    this.scrollTimeout = null;
    this.scrollSteps = 20;
    this.scrollTime = 300;
}

function ScrolledSwitcherGetElement(index) {
    index %= this.elements.length;
    if (index < 0) index += this.elements.length;
    return this.elements[index % this.elements.length];
}

function ScrolledSwitcherDraw(firstIndex, x) {
    while (x > 0) {
        firstIndex--;
        x -= this.getElement(firstIndex).getWidth() + this.spaceWidth;
    }
    var xPos = x;
    var index = firstIndex;
    var element;
    while (xPos < this.viewWidth) {
        element = this.getElement(index);
        element.move(xPos, (this.viewHeight - element.getHeight()) / 2);
        xPos += element.getWidth() + this.spaceWidth;
        index++;
    }
    var lastElement = this.getElement(index);
    /* When the next element collides with the last (on right) element it is hidden
       Such situation may ocurr when the scrolling step is high, then the last element may not be moved */
    if (lastElement.getX() < this.viewWidth && lastElement.getX() > element.getX()) this.getElement(index).move(this.viewWidth, 0);
}

function ScrolledSwitcherScrollStep() {
    //setting size
    var widthModifier = (this.bigWidth - this.smallWidth) * this.stepNumber / this.scrollSteps;
    var heightModifier = (this.bigHeight - this.smallHeight) * this.stepNumber / this.scrollSteps;
    this.getElement(this.focused).resize(this.smallWidth + widthModifier, this.smallHeight + heightModifier);
    this.getElement(this.oldFocused).resize(this.bigWidth - widthModifier, this.bigHeight - heightModifier);
    //setting opacity
    var opacityModifier = (100 - this.opacity) * this.stepNumber / this.scrollSteps;
    this.getElement(this.focused).setOpacity(this.opacity + opacityModifier);
    this.getElement(this.oldFocused).setOpacity(100 - opacityModifier);
    this.draw(this.oldFocused, this.oldScrollX + (this.newScrollX - this.oldScrollX) * this.stepNumber / this.scrollSteps);
}

function ScrolledSwitcherTimedScrollStep() {
    clearTimeout(this.scrollTimeout);
    if (this.stepNumber > this.scrollSteps) {
        this.oldFocused = null;
        return;
    }
    this.scrollStep();
    var element = this;
    this.stepNumber++;
    this.scrollTimeout = setTimeout(function() { element.timedScrollStep(); }, this.scrollTime / this.scrollSteps);
}

function ScrolledSwitcherScroll(direction) {
    if (this.oldFocused != null) {
        clearTimeout(this.scrollTimeout);
        this.stepNumber = this.scrollSteps;
        this.scrollStep();
    }
    this.oldFocused = this.focused;
    this.focused = this.focused - direction;
    if (this.focused >= this.elements.length) this.focused -= this.elements.length;
    else if (this.focused < 0) this.focused += this.elements.length;
    this.oldScrollX = this.getElement(this.oldFocused).getX();
    if (direction < 0) this.newScrollX = this.oldScrollX + direction * (this.smallWidth + this.spaceWidth);
    else { //when scrolling right the big width needs to be scrolled
        this.newScrollX = this.oldScrollX + direction * (this.bigWidth + this.spaceWidth);
    }
    this.stepNumber = 0;
    this.timedScrollStep();
}

function ScrolledSwitcherScrollLeft() {
    this.scroll(1);
}

function ScrolledSwitcherScrollRight() {
    this.scroll(-1);
}

ScrolledSwitcher.prototype.getElement = ScrolledSwitcherGetElement;
ScrolledSwitcher.prototype.draw = ScrolledSwitcherDraw;
ScrolledSwitcher.prototype.scrollStep = ScrolledSwitcherScrollStep;
ScrolledSwitcher.prototype.timedScrollStep = ScrolledSwitcherTimedScrollStep;
ScrolledSwitcher.prototype.scroll = ScrolledSwitcherScroll;
ScrolledSwitcher.prototype.scrollLeft = ScrolledSwitcherScrollLeft;
ScrolledSwitcher.prototype.scrollRight = ScrolledSwitcherScrollRight;
