/**
 * @preserve
 * Copyright 2015-2016 Igor Bezkrovnyi
 * All rights reserved. (MIT Licensed)
 *
 * pointContainer.ts - part of Image Quantization Library
 */
import { Point } from "./point"

/**
 * v8 optimizations done.
 * fromXXX methods are static to move out polymorphic code from class instance itself.
 */
export class PointContainer {
	private _pointArray : Point[];
	private _width : number;
	private _height : number;

	constructor() {
		this._width      = 0;
		this._height     = 0;
		this._pointArray = [];
	}

	getWidth() : number {
		return this._width;
	}

	getHeight() : number {
		return this._height;
	}

	setWidth(width : number) : void {
		this._width = width;
	}

	setHeight(height : number) : void {
		this._height = height;
	}

	getPointArray() : Point[] {
		return this._pointArray;
	}

	clone() : PointContainer {
		var clone     = new PointContainer();
		clone._width  = this._width;
		clone._height = this._height;

		clone._pointArray = [];
		for (var i = 0, l = this._pointArray.length; i < l; i++) {
			clone._pointArray[ i ] = Point.createByUint32(this._pointArray[ i ].uint32 | 0); // "| 0" is added for v8 optimization
		}

		return clone;
	}

	toUint32Array() : Uint32Array {
		var l           = this._pointArray.length,
			uint32Array = new Uint32Array(l);

		for (var i = 0; i < l; i++) {
			uint32Array[ i ] = this._pointArray[ i ].uint32;
		}

		return uint32Array;
	}

	toUint8Array() : Uint8Array {
		return new Uint8Array(this.toUint32Array().buffer);
	}

	static fromHTMLImageElement(img : HTMLImageElement) : PointContainer {
		var width  = img.naturalWidth,
			height = img.naturalHeight;

		var canvas    = document.createElement("canvas");
		canvas.width  = width;
		canvas.height = height;

		var ctx = <CanvasRenderingContext2D>canvas.getContext("2d");
		ctx.drawImage(img, 0, 0, width, height, 0, 0, width, height);

		return PointContainer.fromHTMLCanvasElement(canvas);
	}

	static fromHTMLCanvasElement(canvas : HTMLCanvasElement) : PointContainer {
		var width  = canvas.width,
			height = canvas.height;

		var ctx     = <CanvasRenderingContext2D>canvas.getContext("2d"),
			imgData = ctx.getImageData(0, 0, width, height);

		return PointContainer.fromImageData(imgData);
	}

	static fromNodeCanvas(canvas : any) : PointContainer {
		return PointContainer.fromHTMLCanvasElement(canvas);
	}

	static fromImageData(imageData : ImageData) : PointContainer {
		var width  = imageData.width,
			height = imageData.height;

		return PointContainer.fromCanvasPixelArray(imageData.data, width, height);
		/*
		 var buf8;
		 if (Utils.typeOf(imageData.data) == "CanvasPixelArray")
		 buf8 = new Uint8Array(imageData.data);
		 else
		 buf8 = imageData.data;

		 this.fromUint32Array(new Uint32Array(buf8.buffer), width, height);
		 */
	}

	static fromArray(byteArray : number[], width : number, height : number) : PointContainer {
		var uint8array = new Uint8Array(byteArray);
		return PointContainer.fromUint8Array(uint8array, width, height);
	}

	static fromCanvasPixelArray(data : any, width : number, height : number) : PointContainer {
		return PointContainer.fromArray(data, width, height);
	}

	static fromUint8Array(uint8array : Uint8Array, width : number, height : number) : PointContainer {
		return PointContainer.fromUint32Array(new Uint32Array(uint8array.buffer), width, height);
	}

	static fromUint32Array(uint32array : Uint32Array, width : number, height : number) : PointContainer {
		var container = new PointContainer();

		container._width  = width;
		container._height = height;

		container._pointArray = [];//new Array(uint32array.length);
		for (var i = 0, l = uint32array.length; i < l; i++) {
			container._pointArray[ i ] = Point.createByUint32(uint32array[ i ] | 0); // "| 0" is added for v8 optimization
		}

		return container;
	}
}

