using System;
using System.IO;
using System.Drawing;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

using Plumtree.Remote.Portlet;
using Plumtree.Remote.PRC;
using Plumtree.Remote.PRC.Content;
using Plumtree.Remote.PRC.Content.DataEntryTemplate;
using Plumtree.Remote.PRC.Content.Folder;
using Plumtree.Remote.PRC.Content.Property;
using Plumtree.Remote.PRC.Content.SelectionList;
using Plumtree.Remote.PRC.Content.Item;

namespace DataEntryTemplateSample
{
	public class DETSample : System.Web.UI.Page
	{
		protected System.Web.UI.WebControls.Label lblDETName;
		protected System.Web.UI.WebControls.Panel pnlMain;
		protected System.Web.UI.WebControls.Label lblMessage;
		protected System.Web.UI.WebControls.Button btnCreateItem;

		protected IRemoteSession remoteSession;
		protected IPortletContext portletContext;
		protected IDataEntryTemplate dataEntryTemplate;

		private void Page_Load(object sender, System.EventArgs e)
		{
			try
			{
				portletContext = PortletContextFactory.CreatePortletContext(Request, Response);
				remoteSession = portletContext.GetRemotePortalSession();

				//Get the content factory.
				IContentFactory contentFactory = remoteSession.GetContentFactory();

				//Get the folder containing the data entry template.
				IFolder folder = RetrieveContentFolder(contentFactory);

				//Get the data entry template
				dataEntryTemplate = RetrieveDET(contentFactory, folder);
				
				//Put the name of the data entry template at the top of the form.
				lblDETName.Text = dataEntryTemplate.Name;

				//Create input controls for data entry template.
				RenderDataEntryTemplate(dataEntryTemplate);
			}
			catch(Exception ex)
			{
				DisplayMessage("Exception: " + ex.Message);
			}
		}

		/// <summary>
		/// Gets the Content Server folder used to store all Content
		/// Server objects for our application.
		/// <p>
		/// In this sample, we will create a new folder.  In your
		/// real application you would likely have created the folder																										 * already and will need to query for it here.
		/// </summary>
		private static IFolder RetrieveContentFolder(IContentFactory factory) 
		{
			// Get a folder manager for working with Content Server folders.
			IFolderManager folderManager = factory.GetFolderManager();
		
			//Check to see if the folder has already been created
			IFolder subFolder = folderManager.GetFolderByPath("/C# Web Example - DET");
		
			if(subFolder == null)
			{
				//If the folder is not there we will create our own folder for the sample

				//Get a reference to the root folder. It always exists.
				IFolder rootFolder = folderManager.GetRootFolder();
		
				// Create a new folder.
				subFolder = folderManager.CreateFolder(rootFolder, "C# Web Example - DET");
				subFolder.Store();
			}
			return subFolder;
		}

		/// <summary>
		/// Gets the DET that defines what fields are present in each
		/// customer support incident.
		/// <p>
		/// In this sample, we will create a new DET.  In your real
		/// application, this method would probably query for an existing DET.																										 * existing DET.
		/// </summary>
		private static IDataEntryTemplate RetrieveDET(IContentFactory factory, IFolder folder)
		{
			//
			// A Data Entry Template object is a collection of
			// property objects.  Each property object represents
			// a field in the records associated with the DET.
			//
			// This sample uses all of the classes of properties
			// available in Content Server.  Each customer support
			// incidents will have:
			//   (integer)         Incident ID
			//   (boolean)         If the incident has been resolved
			//   (float)           Incident severity rating
			//   (date)            Date the incident was opened
			//   (text line)       Customer name
			//   (item reference)  Link to other content item representing the customer
			//   (selection list)  The product the incident was reported in
			//   (text block)      Reported problem
			//   (file)            Logs of problem
			//   (image)           Screen shot of problem
			//

			// Get manager objects needed for creating a DET.
			IDataEntryTemplateManager detManager = factory.GetDataEntryTemplateManager();

			// Check to see if the data entry template already exists
			IDataEntryTemplate det = detManager.GetDataEntryTemplate(folder, "Support Incident Data Entry Template");
			if(det != null)
			{
				return det;
			}
			
			IPropertyManager propertyManager = factory.GetPropertyManager();
			ISelectionListManager slManager = factory.GetSelectionListManager();

			// Create a DET object.
			det = detManager.CreateDataEntryTemplate(folder, "Support Incident Data Entry Template");
		
			// Add an integer property.
			IIntegerProperty incident = propertyManager.CreateIntegerProperty("Incident ID", "The ticket number for this incident.");
			det.AddProperty(incident);
		
			// Add a boolean property
			IBooleanProperty resolved = propertyManager.CreateBooleanProperty("Resolved", "True if the incident has been closed; false if it is still open.");
			det.AddProperty(resolved);
		
			// Add a double property.
			IDoubleProperty severity = propertyManager.CreateDoubleProperty("Severity", "Percentage stating how severe the incident is.");
			det.AddProperty(severity);

			// Add a date property.
			IDateProperty opened = propertyManager.CreateDateProperty("Date Opened", "The date and time the incident was reported.");
			det.AddProperty(opened);
		
			// Add a text line property.
			//  Text lines are brief strings without newline characters.
			//  Use the text block property for storing longer strings.
			ITextLineProperty customerName = propertyManager.CreateTextLineProperty("Customer Name", "The name of the customer.");  
			det.AddProperty(customerName);
		
			// Add an item reference property.
			//  An item reference links to another content item.  The
			//  content item does not have to be associated with the
			//  same DET.  For example, we will link to a fictional
			//  content item representing the customer that is having
			//  the support problem; which would be associated with
			//  a DET representing customers.
			//
			//  Not shown is the item collection property.  It is
			//  similar to the item reference property, but links to
			//  multiple content items.
			IItemReferenceProperty customerData = propertyManager.CreateItemReferenceProperty("Customer Information", "Links to information about the customer such as the contact and their phone number.");
			det.AddProperty(customerData);
		
			// Add a selection list property.
			//  A selection list is a defined set of choices of which
			//  one may be selected.  This can be visualized as a
			//  drop down box.
			
			//Check to see if the selection list already exists
			ISelectionList selectionList = null;
			ISelectionList[] selectionLists = slManager.GetSelectionLists(folder);
			foreach(ISelectionList sl in selectionLists)
			{
				if(sl.Name.Equals("Products Selection List"))
				{
					selectionList = sl;
					break;
				}
			}
			
			if(selectionList == null)
			{
				string[] listValues = {"Portal", "Search Server", "Collaboration Server", "Content Server", "Analytics"};
				selectionList = slManager.CreateSelectionList(folder, "Products Selection List", listValues);
				selectionList.Store();
			}

			ISelectionListProperty products = propertyManager.CreateSelectionListProperty("Product", "The product which the support incident is opened against", selectionList);
			det.AddProperty(products);   
		
			// Add a text block property.
			//  Text block properties are used to store long strings
			//  that can span many lines.  For short strings contained
			//  on only one line, use the text line property instead.
			ITextBlockProperty description = propertyManager.CreateTextBlockProperty("Incident Description", "A writeup summarizing the problem the customer is experiencing.");
			det.AddProperty(description);
		
			// Add a file property.
			IFileProperty log = propertyManager.CreateFileProperty("Log File", "A log file taken while the problem occurred.");
			det.AddProperty(log);

			// Add an image property.
			IImageProperty screenShot = propertyManager.CreateImageProperty("Screen Shot", "A screen shot of the problem.");
			det.AddProperty(screenShot);

			// Actually store the DET and all the properties associated with it.
			det.Store();

			return det;
		}

		/// <summary>
		/// Create all the controls for a given Data Entry Template.  The type of
		/// control depends on the type of property.
		/// </summary>
		/// <param name="dataEntryTemplate"></param>
		private void RenderDataEntryTemplate(IDataEntryTemplate dataEntryTemplate)
		{
			Table table = new Table();
			table.ID = "Main DET Table";

			//Add TextBox to enter Content Item Name
			TextBox textBox = new TextBox();
			textBox.ID = "Content Item Name";
			AddTableRow(table, "Content Item Name", textBox, "");

			//Loop through all the properties and add them to the table based on property type
			IBaseProperty[] allProperties = dataEntryTemplate.GetAllProperties();
			foreach(IBaseProperty property in allProperties)
			{
				//Check for different types of properties
				IBooleanProperty boolProp = property as Plumtree.Remote.PRC.Content.Property.IBooleanProperty;
				if(boolProp != null)
				{
					CheckBox checkBox = new CheckBox();
					checkBox.ID = property.Name;

					AddTableRow(table, property.DisplayName, checkBox, property.Description);
				}

				IDateProperty dateProp = property as Plumtree.Remote.PRC.Content.Property.IDateProperty;
				if(dateProp != null)
				{
					textBox = new TextBox();
					textBox.ID = property.Name;

					AddTableRow(table, property.DisplayName, textBox, property.Description);
				}

				IDoubleProperty doubleProp = property as Plumtree.Remote.PRC.Content.Property.IDoubleProperty;
				if(doubleProp != null)
				{
					textBox = new TextBox();
					textBox.ID = property.Name;

					AddTableRow(table, property.DisplayName, textBox, property.Description);
				}

				IFileProperty fileProp = property as Plumtree.Remote.PRC.Content.Property.IFileProperty;
				if(fileProp != null)
				{
					//The HtmlInputFile control requires the 2.2 .NET WebControls to work properly
					//Also make sure the Html Form has the attribute enctype=multipart/form-data
					HtmlInputFile inputFile = new HtmlInputFile();
					inputFile.ID = property.Name;

					//Using an HtmlInputFile control will take us out of the portal when there
					//is a postback.  We could use something like portletContext.GetResponse().ReturnToPortal();
					//to get back to the portal after the postback. For now we'll omit the control for simplicity.
				
					//AddTableRow(table, property.DisplayName, inputFile, property.Description);
					AddTableRow(table, property.DisplayName, new LiteralControl(""), property.Description);
				}

				IImageProperty imageProp = property as Plumtree.Remote.PRC.Content.Property.IImageProperty;
				if(imageProp != null)
				{
					//The HtmlInputFile control requires the 2.2 .NET WebControls to work properly
					//Also make sure the Html Form has the attribute enctype=multipart/form-data
					HtmlInputFile inputFile = new HtmlInputFile();
					inputFile.ID = property.Name;

					//Using an HtmlInputFile control will take us out of the portal when there
					//is a postback.  We could use something like portletContext.GetResponse().ReturnToPortal();
					//to get back to the portal after the postback. For now we'll omit the control for simplicity.
					
					//AddTableRow(table, property.DisplayName, inputFile, property.Description);
					AddTableRow(table, property.DisplayName, new LiteralControl(""), property.Description);
				}
				
				IIntegerProperty integerProp = property as Plumtree.Remote.PRC.Content.Property.IIntegerProperty;
				if(integerProp != null)
				{
					textBox = new TextBox();
					textBox.ID = property.Name;

					AddTableRow(table, property.DisplayName, textBox, property.Description);
				}

				IItemReferenceProperty itemRefProp = property as Plumtree.Remote.PRC.Content.Property.IItemReferenceProperty;
				if(itemRefProp != null)
				{
					//We could query for valid content items and display them in a control
					//or display content items based on some other business logic.
					//For the sample we'll leave this blank.
					AddTableRow(table, property.DisplayName, new LiteralControl(""), property.Description);
				}

				ISelectionListProperty selectionListProp = property as Plumtree.Remote.PRC.Content.Property.ISelectionListProperty;
				if(selectionListProp != null)
				{
					DropDownList dropDown = new DropDownList();
					dropDown.ID = property.Name;

					ISelectionList selectionList = selectionListProp.GetSelectionList();
					String[] values = selectionList.GetValues();
					foreach(String val in values)
					{
						dropDown.Items.Add(val);
					}

					AddTableRow(table, property.DisplayName, dropDown, property.Description);
				}

				ITextBlockProperty textBlockProp = property as Plumtree.Remote.PRC.Content.Property.ITextBlockProperty;
				if(textBlockProp != null)
				{
					HtmlTextArea textArea = new HtmlTextArea();
					textArea.ID = property.Name;

					AddTableRow(table, property.DisplayName, textArea, property.Description);
				}

				ITextLineProperty textLineProp = property as Plumtree.Remote.PRC.Content.Property.ITextLineProperty;
				if(textLineProp != null)
				{
					textBox = new TextBox();
					textBox.ID = property.Name;

					AddTableRow(table, property.DisplayName, textBox, property.Description);
				}
			}

			//Add the table to the main panel
			pnlMain.Controls.Add(table);
		}

		/// <summary>
		/// Create button click event handler
		/// </summary>
		private void btnCreateItem_Click(object sender, System.EventArgs e)
		{
			try
			{
				//Get the Content Item Manager
				IContentFactory contentFactory = remoteSession.GetContentFactory();		
				IContentItemManager contentItemManager = contentFactory.GetContentItemManager();

				// Create a new Content Item.
				String contentItemName = ((TextBox)pnlMain.FindControl("Content Item Name")).Text;
				IContentItem contentItem = contentItemManager.CreateContentItem(
													dataEntryTemplate.GetContainingFolder(),
													contentItemName, 
													dataEntryTemplate);

				// Assign the fields of the content item.
				// Each field is defined by the DET corresponding to the content item.
				IBaseProperty[] props = dataEntryTemplate.GetAllProperties();

				Table table = (Table)pnlMain.FindControl("Main DET Table");

				foreach(TableRow row in table.Rows)
				{
					foreach(Control control in row.Cells[1].Controls)
					{
						//NOTE: Even though RenderDataEntryTemplate dynamically creates
						//controls for any data entry template, this method has been hard-coded 
						//for the data entry template we've created in RetrieveDET for clarity.
						switch(control.ID)
						{
							case "Incident ID":
								contentItem.SetIntegerPropertyValue(props[0], Convert.ToInt32(((TextBox)control).Text));
								break;
						
							case "Resolved":
								contentItem.SetBooleanPropertyValue(props[1], ((CheckBox)control).Checked);
								break;
						
							case "Severity":
								contentItem.SetDoublePropertyValue(props[2], Convert.ToDouble(((TextBox)control).Text));
								break;

							case "Date Opened":
								contentItem.SetDatePropertyValue(props[3], DateTime.Parse(((TextBox)control).Text));
								break;

							case "Customer Name":
								contentItem.SetTextLinePropertyValue(props[4], ((TextBox)control).Text);
								break;

							case "Customer Information":
								//IContentItem customer = contentItemManager.GetContentItem(dataEntryTemplate.GetContainingFolder(), "Customer X");
								//contentItem.SetItemReferencePropertyValue(props[5], customer);
								break;

							case "Product":
								contentItem.SetSelectionListPropertyValue(props[6], ((DropDownList)control).SelectedValue);
								break;

							case "Incident Description":
								contentItem.SetTextBlockPropertyValue(props[7], ((HtmlTextArea)control).Value);
								break;

							case "Log File":
								//The HtmlInputFile control requires the 2.2 .NET WebControls to work properly
								//Also make sure the Html Form has the attribute enctype=multipart/form-data
								HttpPostedFile postedLogFile = ((HtmlInputFile)control).PostedFile;
								if(postedLogFile != null)
								{
									String fileName = Path.GetFileName(postedLogFile.FileName);
									if(fileName != "")
									{
										contentItem.SetFilePropertyValue(props[8], fileName, postedLogFile.InputStream);
									}
								}
								break;

							case "Screen Shot":
								//The HtmlInputFile control requires the 2.2 .NET WebControls to work properly
								//Also make sure the Html Form has the attribute enctype=multipart/form-data
								HttpPostedFile postedScreenFile = ((HtmlInputFile)control).PostedFile;
								if(postedScreenFile != null)
								{
									String fileName = Path.GetFileName(postedScreenFile.FileName);
									if(fileName != "")
									{
										contentItem.SetImagePropertyValue(props[9], fileName, postedScreenFile.InputStream);
									}
								}
								break;
							
							default:
								//do nothing
								break;
						}
					}
				}

				//Store the content Item
				contentItemManager.CheckInItem(contentItem, "Created by DET Sample Portlet");

				//Display a message about the new content item
				DisplayMessage("Content Item " + contentItemName + " Created");
			}
			catch(Exception ex)
			{
				DisplayMessage("Exception: " + ex.Message);
			}
		}

		/// <summary>
		/// Add a content property row to an HTML table
		/// </summary>
		/// <param name="table">Table to add row to</param>
		/// <param name="name">Name of property being added</param>
		/// <param name="control">Input control for this property</param>
		/// <param name="description">Description of property</param>
		private static void AddTableRow(Table table, String name, Control control, String description)
		{
			TableRow row = new TableRow();
			TableCell cell = new TableCell();
				
			//Add Name to first column of first row
			cell.Text = name;
			cell.Font.Bold = true;
			row.Cells.Add(cell);

			//Add Control to second column of first row
			cell = new TableCell();
			cell.Controls.Add(control);
			row.Cells.Add(cell);

			//Add first row to table
			table.Rows.Add(row);

			//add description to second column of second row so
			//it is under the control
			row = new TableRow();
			cell = new TableCell();
				
			row.Cells.Add(cell);
			cell = new TableCell();

			cell.Text = description;
			row.Cells.Add(cell);

			table.Rows.Add(row);
		}


		/// <summary>
		/// Displays an error message in red
		/// </summary>
		/// <param name="message">message to display</param>
		private void DisplayMessage(string message)
		{
			lblMessage.Text = message;
			lblMessage.ForeColor = Color.Red;			
		}

		#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);
		}
		
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{    
			this.btnCreateItem.Click += new System.EventHandler(this.btnCreateItem_Click);
			this.Load += new System.EventHandler(this.Page_Load);

		}
		#endregion
	}
}
