/* Copyright 2009 Palm, Inc.  All rights reserved. */

Photos.Model.LocalFullscreen = Class.create(Photos.Model.Fullscreen, {
	initialize: function($super, albumID, albumName, index) {
		$super(albumID, albumName, index);
		this.bigArray = new Mojo.Model.BigArray(
					this._requestImagesList.bind(this));
		this.total = -1;
		this.isIdle = false;
		this.windowedImages = [];
		this.windowSize = 12;
	},

	aboutToActivate: function(appWindow) {
		this.rowRequester = new Photos.Common.RowRequester(appWindow);
		this.rowRequester.pause();
		this.bigArray.requestFullWindow();
	},

	// Mandatory callbacks for the ImageFlipView widget ==============

	_doCallback: function(callback, image) {
		if (!image) {
			if (callback === this._centerCB) {
				delete this.centerUrl;
			}
			return callback(null);
		}
		if (callback === this._centerCB) {
			this.centerUrl = image.imagePath;
		}
		return callback(image.imagePath, image.imagePictureUrl,
							image.imageName);
	},

	runCallbacks: function() {
		var index = this.index;
		if (index < 0) {
			return;
		}
		var ret = this.bigArray.slice(index - 1, index + 2, true);
		if (index - 1 < 0) {
			this._doCallback(this._leftCB, null);
			this._doCallback(this._centerCB, ret[0]);
			this._doCallback(this._rightCB, ret[1]);
		} else {
			this._doCallback(this._leftCB, ret[0]);
			this._doCallback(this._centerCB, ret[1]);
			this._doCallback(this._rightCB, ret[2]);
		}
	},

	preloadImageExists: function(imageID) {
		for (var i = 0; i < this.windowedImages.length; i++) {
			if (this.windowedImages[i].imageID === imageID) {
				return true;
			}
		}
		return false;
	},

	addWindowedImage: function(image) {
		if (this.windowedImages.length === this.windowSize) {
			this.windowedImages.shift();
		}
		this.windowedImages[this.windowedImages.length] = image;
	},

	rebuildWindow: function(newIndex) {
		var newWindow = this.bigArray.slice(
			newIndex - (this.windowSize / 2),
			newIndex + (this.windowSize / 2) + 1, false);
		for (var i = 0; i < newWindow.length; i++) {
			if (newWindow[i] === null) {
				Mojo.Log.info("Service is down or not responding");
				continue;
			}
			if (this.preloadImageExists(newWindow[i].imageID)) {
				Mojo.Log.info("Already preloaded:"+ newWindow[i].imageID);
				continue;
			}
			this.addWindowedImage(newWindow[i]);
			// this index + i is not entirely correct as slice does
			// not return empty elements for out of bound queries,
			// the window hopefully should grow correct over
			// time anyway as more images are preloaded.
			this.rowRequester.load(
				newIndex + i,
				this.loadImage.bind(this, newWindow[i]));
		}
	},

	jumpTo: function($super, newIndex) {
		if (this.gotResponse) {
			var ret = $super(newIndex);
			if (ret) {
				this.rebuildWindow(newIndex);
				if (this.isIdle) {
					this.rowRequester.resume(newIndex);
				}
			}
			return ret;
		} else {
			this.desiredIndex = newIndex;
			return true;
		}
	},

	canRemove: function() {
		if (this.centerUrl && this.centerUrl.indexOf(":") === -1) {
			// if defined and not a media sync image, allow delete
			return true;
		}
		return false;
	},

	remove: function(offset) {
		// manually maintaining total since big array tends to get
		// crazy with requesting the images and fs changes may not
		// have propagated through to the indexer after a remove.
		this.total -= 1;
		this.bigArray.noticeRemovedItems(offset, 1);
		this.runCallbacks();
	},

	canAssignToContact: function() {
		return true;
	},

	canShareFamily: function() {
		return true;
	},

	canSetWallpaper: function() {
		return true;
	},

	canEmail: function() {
		return true;
	},

	canMMS: function() {
		return true;
	},

	canUpload: function() {
		return true;
	},

	getLowResUrl: function(url) {
		return (Photos.Common.extractfsPath + encodeURIComponent(url) +
			(url.indexOf(":") >= 0 ? ":" : ":0:0:") + "160:160:3");
	},

	idleStart: function() {
		this.isIdle = true;
		if (this.gotResponse) {
			this.rowRequester.resume(this.index);
		}
	},

	idleStop: function() {
		this.isIdle = false;
		this.rowRequester.pause();
	},

	loadImage: function(image, complete) {
		var newImage = document.createElement("img");
		function wrapper() {
			newImage.onload = null;
			newImage.onerror = null;
			Mojo.Log.info("Preload complete: " + url);
			complete();
		}
		newImage.onload = wrapper;
		newImage.onerror = wrapper;
		var url = this.getLowResUrl(
			image.imagePictureUrl || image.imagePath);
		Mojo.Log.info("Preload: " + url);
		newImage.src = url;
	},

	// Internal functions =======================================
	_responseConvert: function(offset, limit, response) {
		if (!response || !response.returnValue) {
			Mojo.Log.info("Error in getting service reply!");
			this.bigArray.setLength(0);
			this.index = 0;
			this.total = -1;
			return;
		}

		this.bigArray.noticeUpdatedItems(offset, response.images);
		if (this.total === -1) {
			this.total = parseInt(response.imagesTotal, 10);
			this.bigArray.setLength(this.total);
		}
		if (!this.gotResponse) {
			this.gotResponse = true;
			if (this.desiredIndex !== undefined) {
				this.jumpTo(this.desiredIndex);
				delete this.desiredIndex;
			}
		}
		this.runCallbacks();
	},

	_requestImagesList: function(offset, limit) {
		Mojo.Log.info("Requesting at offset:", offset, "limit:", limit);
		Photos.Service.listImages(
			offset, limit, "", this.albumID, false,
			this._responseConvert.bind(this, offset, limit),
			this.controller);
	}
});

