/*
	Slider Object
	Copyright © 2014-2019 Harry Whitfield

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License as
	published by the Free Software Foundation; either version 2 of
	the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public
	License along with this program; if not, write to the Free
	Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
	MA	02110-1301	USA

	Slider Object - version 0.7 - browser version
	12 February, 2019
	Copyright © 2014-2019 Harry Whitfield
	mailto:g6auc@arrl.net
*/

/*jslint browser, devel, this */

/*global newImage, moveObj, left, vtop, scale, window */

/*property
    clientX, clientY, getValue, hOff, hOffset, height, knob, knobDelta,
    knobSize, left, mouseIsDown, onmousedown, onmouseleave, onmousemove,
    onmouseup, ontouchend, ontouchmove, ontouchstart, preventDefault, prototype,
    round, scale, scrollX, scrollY, setValue, slideSize, sliderType, slot,
    stopPropagation, targetTouches, touchcancel, touchmove, vOff, vOffset, vtop,
    width
*/

var Slider = function (sliderType, hOffset, vOffset, width, height, left, vtop, imgFolder, zOrder, scale, report) {
	"use strict";
	/*
		sliderType must be one of:
			"horizontal"
			"vertical"
	*/

	var base = imgFolder + "/Sliders/";
	var slotSrc = base + sliderType + "Slot.png";
	var knobSrc = base + "sliderKnob.png";

	var knobSize = 80;		// srcWidth and srcHeight of the knob image
	var knobDelta = 40;		// knobSize / 2
	var slideSize = 20;		// breadth of the slot image
	var slideDelta = 30;	// knobDelta - slideSize / 2

	var that = this;

	this.sliderType = sliderType;
	this.left = left;
	this.vtop = vtop;
	this.scale = scale;

//	this.knobSize = Math.round(knobSize * scale);
	this.knobDelta = Math.round(knobDelta * scale);
	this.slideSize = Math.round(slideSize * scale);

	this.mouseIsDown = false;

	switch (sliderType) {
	case "horizontal":
		this.slot = newImage(hOffset, vOffset, width + knobSize - knobDelta, slideSize, slotSrc, zOrder, 1.0);
//		this.slot.width = Math.round((width + knobSize - knobDelta) * scale);
//		this.slot.height = Math.round(slideSize * scale);
		break;
	case "vertical":
		this.slot = newImage(hOffset, vOffset, slideSize, height + knobSize - knobDelta, slotSrc, zOrder, 1.0);
//		this.slot.width = Math.round(slideSize * scale);
//		this.slot.height = Math.round((height + knobSize - knobDelta) * scale);
		break;
	default:
		slotSrc = base + "errors.png";
		this.slot = newImage(hOffset, vOffset, 64, 64, slotSrc, zOrder, 1.0);
//		this.slot.width = Math.round(64 * scale);
//		this.slot.height = Math.round(64 * scale);
	}

//	this.slot.hOffset = Math.round(hOffset * scale);
//	this.slot.vOffset = Math.round(vOffset * scale);

	var noop = function (evt) {
		evt.preventDefault();
	};

	this.slot.onmousedown = noop;
	this.slot.onmouseup = noop;
	this.slot.onmouseleave = noop;
	this.slot.onmousemove = noop;

	this.slot.ontouchstart = noop;
	this.slot.ontouchend = noop;
	this.slot.touchcancel = noop;
	this.slot.touchmove = noop;

	switch (sliderType) {
	case "horizontal":
		this.knob = newImage(hOffset - knobDelta + slideSize, vOffset - slideDelta, knobSize, knobSize, knobSrc, zOrder + 1, 1.0);
//		this.knob.hOffset = Math.round((hOffset - knobDelta + slideSize) * scale);
//		this.knob.vOffset = Math.round((vOffset - slideDelta) * scale);
		this.knob.hOff = this.knob.hOffset;
		break;
	case "vertical":
		this.knob = newImage(hOffset - slideDelta, vOffset - knobDelta + slideSize, knobSize, knobSize, knobSrc, zOrder + 1, 1.0);
//		this.knob.hOffset = Math.round((hOffset - slideDelta) * scale);
//		this.knob.vOffset = Math.round((vOffset - knobDelta + slideSize) * scale);
		this.knob.vOff = this.knob.vOffset;
		break;
	}

	this.knob.onmousedown = function (evt) {
		evt.preventDefault();
		that.mouseIsDown = true;
	};

	this.knob.onmouseup = function (evt) {
		evt.preventDefault();
		that.mouseIsDown = false;
	};

	this.knob.onmouseleave = function (evt) {
		evt.preventDefault();
		that.mouseIsDown = false;
	};

    this.knob.ontouchstart = function (evt) {
        evt.stopPropagation();
        evt.preventDefault();
        that.mouseIsDown = true;
    };

	this.knob.ontouchend = function (evt) {
        evt.stopPropagation();
        evt.preventDefault();
        that.mouseIsDown = false;
    };

	this.knob.touchcancel = function (evt) {
        evt.stopPropagation();
        evt.preventDefault();
        that.mouseIsDown = false;
    };

	var knobMove = function (posX, posY) {	// posX, posY are scaled
        var hOff;
        var vOff;
        var scrollX = window.scrollX;		// scrollX, scrollY are scaled
        var scrollY = window.scrollY;
        var lowX;
        var lowY;
        var highX;
        var highY;

		if (!that.mouseIsDown) {
			return;
		}

		switch (that.sliderType) {
		case "horizontal":
			hOff = posX + scrollX - that.left - that.knobDelta;
			lowX = that.slot.hOffset - that.knobDelta + that.slideSize;
			if (hOff < lowX) {
				hOff = lowX;
			}
			highX = lowX + that.slot.width - that.knobDelta;
			if (hOff > highX) {
				hOff = highX;
			}
			moveObj(that.knob, hOff / that.scale, that.knob.vOffset / that.scale);
			that.knob.hOff = hOff;
			report((hOff - lowX) / that.scale);
			break;
		case "vertical":
			vOff = posY + scrollY - that.vtop - that.knobDelta;
			lowY = that.slot.vOffset - that.knobDelta + that.slideSize;
			if (vOff < lowY) {
				vOff = lowY;
			}
			highY = lowY + that.slot.height - that.knobDelta;
			if (vOff > highY) {
				vOff = highY;
			}
			moveObj(that.knob, that.knob.hOffset / that.scale, vOff / that.scale);
			that.knob.vOff = vOff;
			report((vOff - lowY) / that.scale);
			break;
		default:
			alert("Invalid slider type: " + that.sliderType);
		}
	};

	this.knob.onmousemove = function (evt) {
        var posX;
        var posY;

        evt.stopPropagation();
        evt.preventDefault();

      	posX = evt.clientX;
        posY = evt.clientY;
        knobMove(posX, posY);
    };

    this.knob.ontouchmove = function (evt) {
        var posX;
        var posY;

        evt.stopPropagation();
        evt.preventDefault();

      	posX = evt.targetTouches[0].clientX;
        posY = evt.targetTouches[0].clientY;
        knobMove(posX, posY);
    };
};

Slider.prototype.getValue = function () {
	"use strict";
	var lowX;
	var lowY;

	switch (this.sliderType) {
	case "horizontal":
		lowX = this.slot.hOffset - this.knobDelta + this.slideSize;
		return (this.knob.hOff - lowX) / this.scale;
	case "vertical":
		lowY = this.slot.vOffset - this.knobDelta + this.slideSize;
		return (this.knob.vOff - lowY) / this.scale;
	}
};

Slider.prototype.setValue = function (value) {
	"use strict";
    var hOff;
    var vOff;
    var lowX;
    var lowY;
    var highX;
    var highY;

    value = value * this.scale;

	switch (this.sliderType) {
	case "horizontal":
		lowX = this.slot.hOffset - this.knobDelta + this.slideSize;
		hOff = lowX + value;
		if (hOff < lowX) {
			hOff = lowX;
		}
		highX = lowX + this.slot.width - this.knobDelta;
		if (hOff > highX) {
			hOff = highX;
		}
		moveObj(this.knob, hOff / this.scale, this.knob.vOffset / this.scale);
		this.knob.hOff = hOff;
		return (hOff - lowX) / this.scale;
	case "vertical":
		lowY = this.slot.vOffset - this.knobDelta + this.slideSize;
		vOff = lowY + value;
		if (vOff < lowY) {
			vOff = lowY;
		}
		highY = lowY + this.slot.height - this.knobDelta;
		if (vOff > highY) {
			vOff = highY;
		}
		moveObj(this.knob, this.knob.hOffset / this.scale, vOff / this.scale);
		this.knob.vOff = vOff;
		return (vOff - lowY) / this.scale;
	}
};

/*
var testInfo = newDiv(0, 500, 1, "testInfo");

function print(value) {
	"use strict";
	testInfo.innerHTML = String(value);
}

var slider1 = new Slider("horizontal", 100, 100, 200, 20, left, vtop, "Resources/", 10, scale, print);
var slider2 = new Slider("vertical", 100, 200, 20, 200, left, vtop, "Resources/", 10, scale, print);
//alert("setValue: " + slider1.setValue(21));
//alert("setValue: " + slider2.setValue(157));
//alert("getValue: " + slider1.getValue());
//alert("getValue: " + slider2.getValue());
var slider3 = new Slider("vertical", 300, 200, 20, 200, left, vtop, "Resources/", 10, scale, print);
*/