namespace Orciid.UserControls
{
	using System;
	using System.Data;
	using System.Drawing;
	using System.Collections;
	using System.Web;
	using System.Web.UI;
	using System.Web.UI.WebControls;
	using System.Web.UI.HtmlControls;
	using Orciid.Core;
	using Orciid.PageTemplate;

	public class ImageRecordEditor : OrciidUserControl, INamingContainer
	{
		private Orciid.Core.Image imagedatasource = null;
		private Collection collectiondatasource = null;
		private string inputgroupstyle = "";
		private Hashtable imagefields;
		private ImageIdentifier id;
		private bool personalimage = false;
		
		private const string clientsideresource = 
@"<script language='JavaScript'>
function EditorFieldClear(button) {
	var n = button.name.substring(0, button.name.lastIndexOf(':') + 1);
	n = n + 'value' + button.name.substring(n.length + 6, button.name.length);
	for (var i = 0; i < button.form.elements.length; i++) {
		var e = button.form.elements[i];
		if (e.name && e.name.substring(0, n.length) == n && 
			(n.length == e.name.length || e.name.charAt(n.length) == '_')) {
			if (e.length)
				e.selectedIndex = 0;
			else 
				e.value = '';
		}
	}
}
</script>
<style type='text/css'>
.editorcontrol { width: 300px; }
</style>";

		protected override void LoadViewState(object savedState) 
		{
			if (savedState != null)
			{
				base.LoadViewState(savedState);
				if (ViewState["id"] is ImageIdentifier)
					id = (ImageIdentifier)ViewState["id"];
				if (ViewState["imagefields"] is Hashtable)
					imagefields = (Hashtable)ViewState["imagefields"];
				if (ViewState["personalimage"] is bool)
					personalimage = (bool)ViewState["personalimage"];
			}
		}

		protected override object SaveViewState()
		{
			ViewState["id"] = id;
			ViewState["imagefields"] = imagefields;
			ViewState["personalimage"] = personalimage;
			return base.SaveViewState();
		}

		public object DataSource
		{
			set
			{
				imagedatasource = null;
				collectiondatasource = null;
				if (value is Orciid.Core.Image)
				{
					imagedatasource = value as Orciid.Core.Image;
					personalimage = (imagedatasource.UserID != 0);
				}
				else if (value is Collection)
					collectiondatasource = value as Collection;
			}
			get
			{
				if (imagedatasource != null)
					return imagedatasource;
				else
					return collectiondatasource;
			}
		}

		public string InputGroupStyle
		{
			set
			{
				if (value == null)
					inputgroupstyle = "";
				else
					inputgroupstyle = value;
			}
			get
			{
				return inputgroupstyle;
			}
		}

		public bool PersonalImage
		{
			set
			{
				personalimage = value;
			}
			get
			{
				return personalimage;
			}
		}

		private string InputGroupStyleAttribute()
		{
			if (inputgroupstyle.Length == 0)
				return "";
			else
				return String.Format(" style=\"{0}\"", inputgroupstyle);
		}

		public override void DataBind() 
		{
			base.OnDataBinding(EventArgs.Empty);
			Controls.Clear();
//			if (HasChildViewState)
				ClearChildViewState();
			CreateControlHierarchy(true);
			ChildControlsCreated = true;
//			if (!IsTrackingViewState)
				TrackViewState();
		}

		protected override void CreateChildControls() 
		{
			Controls.Clear();
			if (imagefields != null) 
				CreateControlHierarchy(false);
		}

		private void CreateControlHierarchy(bool useDataSource) 
		{
			if (!Page.IsClientScriptBlockRegistered("ImageRecordEditor"))
				Page.RegisterClientScriptBlock("ImageRecordEditor", clientsideresource);

			Hashtable imgf = null;

			if (useDataSource == false) 
				imgf = imagefields;
			
			Controls.Add(new LiteralControl(
				"<table border=\"0\" cellpadding=\"3\" cellspacing=\"3\">\n"));

			int linecount = 0;

			if (imgf != null)
			{
				// recreate form from viewstate
				Collection coll = Collection.GetByID(id.CollectionID);
				Controls.Add(new LiteralControl(String.Format(
					"<tr><td valign=\"top\"><b>{0}</b></td><td valign=\"top\">{1}</td></tr>\n", 
					GetLocalString("Collection", "Collection:"),
					coll.Title)));
				foreach (Field field in coll.GetFields())
					CreateField(field, (int)imgf[field.ID], null, ref linecount);
				CreateResourceField(null, ref linecount, !personalimage);
			}
			else if (imagedatasource != null || collectiondatasource != null)
			{
				// create form from datasource
				if (imagedatasource != null)
				{
					id = imagedatasource.ID;
				}
				else
				{
					id.CollectionID = collectiondatasource.ID;
					id.ID = 0;
				}
				imagefields = new Hashtable();
				Collection coll = Collection.GetByID(id.CollectionID);
				Controls.Add(new LiteralControl(String.Format(
					"<tr><td valign=\"top\"><b>{0}</b></td><td valign=\"top\">{1}</td></tr>\n", 
					GetLocalString("Collection", "Collection:"),
					coll.Title)));
				foreach (Field field in coll.GetFields())
				{
					if (imagedatasource != null)
					{
						CreateField(field, imagedatasource[field].Count, imagedatasource[field], ref linecount);
						imagefields.Add(field.ID, Math.Max(imagedatasource[field].Count, 1));
					}
					else
					{
						CreateField(field, 0, null, ref linecount);
						imagefields.Add(field.ID, 1);
					}
				}
				if (imagedatasource != null)
					CreateResourceField(imagedatasource.Resource, ref linecount, imagedatasource.UserID == 0);
				else
					CreateResourceField(null, ref linecount, !personalimage);
			}
			Controls.Add(new LiteralControl("</table>\n"));
		}

		private void CreateField(Field field, int instancecount, FieldData data, ref int linecount)
		{
			int instance = 0; 
			do
			{
				if (instance == 0)
					Controls.Add(new LiteralControl(String.Format(
						"<tr><td valign=\"top\"><b>{0}:</b></td>\n", 
						field.Label)));
				else
					Controls.Add(new LiteralControl("<tr><td></td>\n"));
				Controls.Add(new LiteralControl(String.Format("<td{0}>", InputGroupStyleAttribute())));
				Controls.Add(CreateInputControl(field, instance, data));
				Controls.Add(new LiteralControl("</td><td valign=\"top\">"));
				HtmlInputButton removebutton = new HtmlInputButton();
				removebutton.ID = String.Format("remove_{0}_{1}", field.ID, instance);
				removebutton.Value = " - ";
				removebutton.Attributes["onclick"] = "EditorFieldClear(this);";
				removebutton.EnableViewState = false;
				Controls.Add(removebutton);
				instance++;
				if (instance >= instancecount)
				{
					Controls.Add(new LiteralControl(" "));
					Button addbutton = new Button();
					addbutton.ID = String.Format("add_{0}", field.ID);
					addbutton.Text = " + ";
					addbutton.CommandName = "AddInstance";
					addbutton.CommandArgument = field.ID.ToString();
					addbutton.Command += new CommandEventHandler(InstanceButton_Command);
					Controls.Add(addbutton);
				}
				Controls.Add(new LiteralControl("</td></tr>\n"));
				linecount++;
			} while (instance < instancecount);
		}

		private void CreateResourceField(string resource, ref int linecount, bool editable)
		{
			Controls.Add(new LiteralControl(String.Format(
				"<tr>\n<td valign=\"top\"><b>{0}</b></td>\n<td{1}>",
				GetLocalString("Resource", "Resource:"),
				InputGroupStyleAttribute())));
			TextBox resourcetext = new TextBox();
			resourcetext.Attributes["class"] = "editorcontrol";
			if (!editable)
				resourcetext.ReadOnly = true;
			resourcetext.ID = "resource";
			if (resource != null)
				resourcetext.Text = resource;
			Controls.Add(resourcetext);
			Controls.Add(new LiteralControl(String.Format(
				"<br/><small>{0}</small></td><td></td></tr>\n",
				GetLocalString("ResourceNote", 
				"Note: Modifying the resource does not rename any associated image files"))));
			linecount++;
		}

		// creates input controls for a single field value
		private Control CreateInputControl(Field field, int instance, FieldData data)
		{
			PlaceHolder container;
			switch (field.Type)
			{
				case FieldType.Text:
				case FieldType.ExactText:
					TextBox text = CreateTextBox();
					text.ID = String.Format("value_{0}_{1}", field.ID, instance);
					if (data != null && instance < data.Count)
						text.Text = data[instance];
					return text;
				case FieldType.ControlledList:
					container = new PlaceHolder();
					TextBox cltext = CreateTextBox();
					cltext.ID = String.Format("value_{0}_{1}", field.ID, instance);
					if (data != null && instance < data.Count)
						cltext.Text = data[instance];
					container.Controls.Add(cltext);
					container.Controls.Add(new LiteralControl("<br />"));
					DropDownList dropdownlist = new DropDownList();
					dropdownlist.ID = String.Format("value_{0}_{1}_list", field.ID, instance);
					ControlledList list = ControlledList.GetByID(field.ControlledListID);
					dropdownlist.Items.Add(new ListItem(
						GetLocalString("SelectFromList", "[Select from List]"), "0"));
					if (list != null)
						foreach (DictionaryEntry item in list.GetSortedList())
							if (item.Value.ToString() != "")
								dropdownlist.Items.Add(
									new ListItem(item.Key.ToString(), item.Value.ToString()));
					dropdownlist.Attributes.Add("onchange",
						"this.form.elements[this.name.substring(0,this.name.length-5)].value=this.options[this.selectedIndex].text;this.selectedIndex=0;");
					dropdownlist.Attributes["class"] = "editorcontrol";
					dropdownlist.EnableViewState = false;
					container.Controls.Add(dropdownlist);
					return container;
				case FieldType.Date:
					container = new PlaceHolder();
					TextBox dvtext = CreateTextBox();
					dvtext.ID = String.Format("value_{0}_{1}", field.ID, instance);
					if (data != null && instance < data.Count)
						dvtext.Text = data[instance];
					container.Controls.Add(dvtext);
					container.Controls.Add(new LiteralControl("<br />" +
						GetLocalString("Year", "Year") + " "));
					TextBox sytext = new TextBox();
					sytext.Columns = 8;
					sytext.ID = String.Format("value_{0}_{1}_start", field.ID, instance);
					if (data != null && instance < data.Count)
					{
						int e = ((FieldDataDate)data).GetStartDate(instance);
						if (e != Int32.MinValue)
							sytext.Text = e.ToString();
					}
					container.Controls.Add(sytext);
					container.Controls.Add(new LiteralControl(" " +
						GetLocalString("YearTo", "to") + " "));
					TextBox eytext = new TextBox();
					eytext.Columns = 8;
					eytext.ID = String.Format("value_{0}_{1}_end", field.ID, instance);
					if (data != null && instance < data.Count)
					{
						int e = ((FieldDataDate)data).GetEndDate(instance);
						if (e != Int32.MinValue)
							eytext.Text = e.ToString();
					}
					container.Controls.Add(eytext);
					return container;
				default:
					return new LiteralControl(GetLocalString("NotImplemented", "[not implemented]"));
			}
		}

		// creates a multiline textbox with some default properties
		private TextBox CreateTextBox()
		{
			TextBox box = new TextBox();
			box.TextMode = TextBoxMode.MultiLine;
			box.Attributes["class"] = "editorcontrol";
			box.Rows = 2;
			box.Wrap = true;
			return box;
		}

		private void InstanceButton_Command(object sender, CommandEventArgs e)
		{
			if (e.CommandName == "AddInstance")
			{
				int fieldid = Int32.Parse((string)e.CommandArgument);
				int instances = (int)imagefields[fieldid];
				imagefields[fieldid] = instances + 1;
				int idx = Controls.IndexOf((Button)sender) - 1;
				Collection coll = Collection.GetByID(id.CollectionID);
				Controls.AddAt(idx, new LiteralControl(String.Format("</td></tr>\n<tr><td></td><td{0}>", InputGroupStyleAttribute())));
				Controls.AddAt(idx + 1, CreateInputControl(coll.GetField(fieldid), instances, null));
				Controls.AddAt(idx + 2, new LiteralControl("</td><td valign=\"top\">"));
				HtmlInputButton removebutton = new HtmlInputButton();
				removebutton.ID = String.Format("remove_{0}_{1}", fieldid, instances);
				removebutton.Value = " - ";
				removebutton.Attributes["onclick"] = "EditorFieldClear(this);";
				Controls.AddAt(idx + 3, removebutton);
			}
		}

		public void CommitData()
		{
			if (id.CollectionID == 0 || imagefields == null)
				throw new Exception("Cannot commit data before binding data.");

			Collection coll = Collection.GetByID(id.CollectionID);
			Orciid.Core.Image image;

			if (id.ID == 0)
				image = coll.CreateImage(personalimage);
			else
				image = Orciid.Core.Image.GetByID(id);

			foreach (Field field in coll.GetFields())
			{
				FieldData data = image[field];
				data.RemoveAll();
				int instances = Math.Max((int)imagefields[field.ID], 1);
				for (int instance = 0; instance < instances; instance++)
				{
					string inputname = String.Format("value_{0}_{1}", field.ID, instance);
					string inputvalue = ((TextBox)this.FindControl(inputname)).Text;
					if (inputvalue != "")
					{
						if (field.Type == FieldType.Date)
						{
							string startvalue = ((TextBox)this.FindControl(inputname + "_start")).Text;
							string endvalue = ((TextBox)this.FindControl(inputname + "_end")).Text;
							try
							{
								((FieldDataDate)data).Set(instance, inputvalue, startvalue + "-" + endvalue,
									DateInterpreter.Format.YearOnly);
							}
							catch
							{
								data.Add(inputvalue);
							}
						}
						else 
							data.Add(inputvalue);
					}
				}
			}
			TextBox resourcebox = this.FindControl("resource") as TextBox;
			if (resourcebox != null)
				image.Resource = resourcebox.Text;
			image.Update();
			DataSource = image;
			DataBind();
		}

		#region Web Form Designer generated code
		override protected void OnInit(EventArgs e)
		{
			//
			// CODEGEN: This call is required by the ASP.NET Web Form Designer.
			//
			InitializeComponent();
			base.OnInit(e);
		}
		

		private void InitializeComponent()
		{
		}
		#endregion
	}
}
