/*******************************************************}
{                                                       }
{               Borland DB Web                          }
{           Data aware Web controls                     }
{  Copyright (c) 2003 Borland Software Corporation      }
{                                                       }
{*******************************************************/

using System;
using System.ComponentModel;
using System.Collections;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Drawing.Design;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
using System.Data;
using System.Reflection;
using System.IO;

namespace Borland.Data.Web
{

	#region ListBoxes
    #region ColumnNameListBox Class
    /// <summary>
    /// Listbox which displays the ColumnNames from a DataTable
    /// </summary>
    internal class ColumnListBox : System.Windows.Forms.ListBox
    {
        private IServiceProvider serviceProvider;
        private IWindowsFormsEditorService editorService;
        private System.Data.DataTable FDataSource;
        private string FOldValue;
        private int oldColumnIndex;
        private ArrayList FLimitType;
        private ArrayList FExcludeList;

        internal ColumnListBox(IServiceProvider serviceProvider, System.Data.DataTable DataSource, string oldValue)
        {
            this.serviceProvider = serviceProvider;
            this.FDataSource = DataSource;
            FOldValue = oldValue;
            editorService = (IWindowsFormsEditorService) serviceProvider.GetService(typeof(IWindowsFormsEditorService));
            SelectionMode = SelectionMode.One;
            FExcludeList = new ArrayList();
            FLimitType = new ArrayList();
            //BorderStyle = BorderStyle.None;
            //IntegralHeight = true;
            SelectedIndexChanged += new EventHandler(OnSelectionChanged);
            Click += new EventHandler(OnListClick);
            KeyDown += new KeyEventHandler(OnListKeyDown);
        }

        public ArrayList LimitType
        {
        		get
            {
            	return FLimitType;
            }
        }

        public ArrayList ExcludeList
        {
        		get
            {
            	return FExcludeList;
            }
        }

        private bool Excluded(string typeName)
        {
        		for( int i = 0; i < FExcludeList.Count; i++ )
            	if(FExcludeList[i].ToString() == typeName )
               	return true;
            return false;
        }

        private bool IsValidType(string sType)
        {
            if( FLimitType.Count == 0 )
            	return true;
        		for( int i = 0; i < FLimitType.Count; i++ )
            	if( FLimitType[i].ToString() == sType )
               	return true;
            return false;
        }

        public bool InitList(string oldValue)
        {
        		bool bFound = false;
            int iExcluded = 0;
            Items.Clear();
            oldColumnIndex = -1;
            if( FDataSource != null)
            {
	         	for( int i = 0; i < FDataSource.Columns.Count; i++ )
	            {
               	if( IsValidType(FDataSource.Columns[i].DataType.FullName) &&
                      !Excluded(FDataSource.Columns[i].DataType.FullName) )
                  {
		     	         Items.Add(FDataSource.Columns[i].ColumnName);
   		     	      if( FDataSource.Columns[i].ColumnName == oldValue )
      		         {
         		      	SelectedIndex = i - iExcluded;
           			   	oldColumnIndex = SelectedIndex;
               		   bFound = true;
			         	}
                  }
                  else
                  	iExcluded++;
               }
            }
            if( !bFound && Items.Count > 0 )
	            SelectedIndex = 0;
            return Items.Count > 0;
        }

        private void OnListClick(object sender, EventArgs e)
        {
            editorService.CloseDropDown();
        }

        private void OnListKeyDown(object sender, KeyEventArgs args)
        {
            if ((int)args.KeyCode == 13)
                this.OnListClick(sender, EventArgs.Empty);
        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
        }
        public int GetSelectedConnectionIndex()
        {
          return SelectedIndex;
        }

        public int OldConnectionIndex
        {
            get { return oldColumnIndex; }
        }

    }
    #endregion

    #region TableNameListBox Class
    /// <summary>
    /// Listbox which displays the TableNames from the DataSet
    /// </summary>
    internal class TableNameListBox : System.Windows.Forms.ListBox
    {
        private IServiceProvider serviceProvider;
        private IWindowsFormsEditorService editorService;
        private System.Data.DataSet FDataSource;
        private string FOldValue;
        private int oldColumnIndex;

        internal TableNameListBox(IServiceProvider serviceProvider, System.Data.DataSet DataSource, string oldValue)
        {
            this.serviceProvider = serviceProvider;
            this.FDataSource = DataSource;
            FOldValue = oldValue;
            editorService = (IWindowsFormsEditorService) serviceProvider.GetService(typeof(IWindowsFormsEditorService));
            SelectionMode = SelectionMode.One;
            //BorderStyle = BorderStyle.None;
            //IntegralHeight = true;
            InitList(oldValue);
            SelectedIndexChanged += new EventHandler(OnSelectionChanged);
            Click += new EventHandler(OnListClick);
            KeyDown += new KeyEventHandler(OnListKeyDown);
        }

        private void InitList(string oldValue)
        {
        		bool bFound = false;
            Items.Clear();
            oldColumnIndex = -1;
            if( FDataSource != null)
            {
	         	for( int i = 0; i < FDataSource.Tables.Count; i++ )
	            {
     	         	Items.Add(FDataSource.Tables[i].TableName);
        	      	if( FDataSource.Tables[i].TableName == oldValue )
                  {
           	   		oldColumnIndex = i;
                     SelectedIndex = i;
                     bFound = true;
                  }
		         }
               if( !bFound )
	            	SelectedIndex = 0;
            }
        }

        private void OnListClick(object sender, EventArgs e)
        {
            editorService.CloseDropDown();
        }

        private void OnListKeyDown(object sender, KeyEventArgs args)
        {
            if ((int)args.KeyCode == 13)
                this.OnListClick(sender, EventArgs.Empty);
        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
        }
        public int GetSelectedConnectionIndex()
        {
          return SelectedIndex;
        }

        public int OldConnectionIndex
        {
            get { return oldColumnIndex; }
        }

    }
    #endregion

    #region DataSourceListBox Class
    /// <summary>
    /// Listbox which displays the TableNames from the DataSet
    /// </summary>
    internal class DataSourceListBox : System.Windows.Forms.ListBox
    {
        private IServiceProvider serviceProvider;
        private IWindowsFormsEditorService editorService;
        private ArrayList Components;
        private object FOldValue;
        private int oldColumnIndex;

        internal DataSourceListBox(IServiceProvider serviceProvider, ComponentCollection components, object oldValue, bool bAllowNone)
        {
            this.serviceProvider = serviceProvider;
            FOldValue = oldValue;
            editorService = (IWindowsFormsEditorService) serviceProvider.GetService(typeof(IWindowsFormsEditorService));
            SelectionMode = SelectionMode.One;
            Components = new ArrayList();
            InitList(oldValue, components, bAllowNone);
            SelectedIndexChanged += new EventHandler(OnSelectionChanged);
            Click += new EventHandler(OnListClick);
            KeyDown += new KeyEventHandler(OnListKeyDown);
        }

        private void InitList(object oldValue, ComponentCollection components, bool bAllowNone)
        {
        		bool bFound = false;
            Items.Clear();
            Components.Clear();
            Components.Add(null);
            Items.Add(BdwResources.GetString("None"));
            if( bAllowNone )
            {
            	SelectedIndex = 0;
               return;
            }
            oldColumnIndex = -1;
            if( components != null )
            {
	         	for( int i = 0; i < components.Count; i++ )
	            {
               	if( components[i] is DataSet || components[i] is DataTable ||
                  		components[i] is DataView )
                  {
                     string sItem = components[i].ToString();
                     int iBracketPos = sItem.IndexOf('[');
                     if( iBracketPos > 0 )
                     	sItem = sItem.Substring(0, iBracketPos -1 );
	     	         	Items.Add(sItem);
                     Components.Add(components[i]);
	        	      	if( oldValue != null && components[i] == oldValue )
   	               {
         	            SelectedIndex = Components.Count -1;
      	     	   		oldColumnIndex = SelectedIndex;
            	         bFound = true;
                     }
                  }
		         }
               if( !bFound )
	            	SelectedIndex = 0;
            }
        }

        private void OnListClick(object sender, EventArgs e)
        {
            editorService.CloseDropDown();
        }

        private void OnListKeyDown(object sender, KeyEventArgs args)
        {
            if ((int)args.KeyCode == 13)
                this.OnListClick(sender, EventArgs.Empty);
        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
        }
        public int GetSelectedConnectionIndex()
        {
          return SelectedIndex;
        }

        public int OldIndex
        {
            get { return oldColumnIndex; }
        }
        public object GetSelectedObject(int index)
        {
        		return Components[index];
        }

    }
    #endregion

    #region CurrentRowListBox Class
    /// <summary>
    /// Listbox which displays the RowId's from a DataTable
    /// </summary>
    internal class RowListBox : System.Windows.Forms.ListBox
    {
        private IServiceProvider serviceProvider;
        private IWindowsFormsEditorService editorService;
        private System.Data.DataTable FDataSource;
        private string FOldValue;
        private int oldColumnIndex;

        internal RowListBox(IServiceProvider serviceProvider, System.Data.DataTable DataSource, string oldValue)
        {
            this.serviceProvider = serviceProvider;
            this.FDataSource = DataSource;
            FOldValue = oldValue;
            editorService = (IWindowsFormsEditorService) serviceProvider.GetService(typeof(IWindowsFormsEditorService));
            SelectionMode = SelectionMode.One;
            //BorderStyle = BorderStyle.None;
            //IntegralHeight = true;
            InitList(oldValue);
            SelectedIndexChanged += new EventHandler(OnSelectionChanged);
            Click += new EventHandler(OnListClick);
            KeyDown += new KeyEventHandler(OnListKeyDown);
        }

        private void InitList(string oldValue)
        {
        		bool bFound = false;
            Items.Clear();
            oldColumnIndex = -1;
            if( FDataSource != null)
            {
	         	for( int i = 0; i < FDataSource.Rows.Count; i++ )
	            {
	     	         Items.Add(Convert.ToString(i));
   	     	      if( Convert.ToString(i) == oldValue )
      	         {
         	      	SelectedIndex = i;
           		   	oldColumnIndex = i;
               	   bFound = true;
			         }
               }
            }
            if( !bFound )
	            SelectedIndex = 0;
        }

        private void OnListClick(object sender, EventArgs e)
        {
            editorService.CloseDropDown();
        }

        private void OnListKeyDown(object sender, KeyEventArgs args)
        {
            if ((int)args.KeyCode == 13)
                this.OnListClick(sender, EventArgs.Empty);
        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
        }
        public int GetSelectedConnectionIndex()
        {
          return SelectedIndex;
        }

        public int OldConnectionIndex
        {
            get { return oldColumnIndex; }
        }

    }
    #endregion
	#endregion ListBoxes

   #region override UITypeEditor

   // handle getting DataSource and TableName for either DBWebControls
   // or other descendents of WebControl such as DBWebCalendarControl
   public class DBWebControlTypeEditor : UITypeEditor
   {
      protected IDBDataSource dataSource;
      protected string tableName;

   	public DBWebControlTypeEditor() : base()
      {
      	dataSource = null;
         tableName = null;
      }
      protected void SetDataSource(ITypeDescriptorContext context)
      {
         object o = DU.GetPropertyValue( context.Instance, "DBDataSource" );
         tableName = GetTableName(context.Instance as WebControl);
         Borland.Data.Web.DBWebDataSource ds = (o as Borland.Data.Web.DBWebDataSource);
         if( ds != null )
         	dataSource = ds as Borland.Data.Web.IDBDataSource;
      }

      protected virtual string GetTableName( WebControl wc )
      {
         if( wc is IDBWebDataLink )
      		return (wc as IDBWebDataLink).TableName;
         else if( wc is DBWebCalendar )
      		return (wc as DBWebCalendar).TableName;
         return null;
      }
   }


   public class ColumnNamePropEditor : DBWebControlTypeEditor
   {
      protected ArrayList FLimitTypesTo;
      protected ArrayList FExcludeTypes;
      public const string LimitTypesChar = "System.Char[]";
      public const string LimitTypesStr = "System.String";

      protected virtual ArrayList LimitTypesTo
      {
      	get
         {
         	return FLimitTypesTo;
         }
      }

      protected virtual ArrayList ExcludeTypes
      {
      	get
         {
         	return FExcludeTypes;;
         }
      }

      public ColumnNamePropEditor() : base()
      {
      	FLimitTypesTo = new ArrayList();
      	FExcludeTypes = new ArrayList();
         FExcludeTypes.Add("System.Byte[]");
         FExcludeTypes.Add("System.Char[]");
         FExcludeTypes.Add("System.TimeSpan");
         FExcludeTypes.Add("System.Object");
      }

      public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
      {
      	if (context != null && context.Instance != null &&  context.Instance is WebControl)
         {
         	try
            {
            	IWindowsFormsEditorService editorService = (IWindowsFormsEditorService)
               provider.GetService(typeof(IWindowsFormsEditorService));
               if (editorService != null && context.OnComponentChanging())
               {
                  SetDataSource(context);

                  System.Data.DataTable dataTable = null;
                  if( dataSource != null )
                  {
                  	Object o = dataSource.GetTableOrView(null, tableName);
                     if( o is DataTable )
                  		dataTable = (o as DataTable);
                     else if ( o is DataView )
                     	dataTable = (o as DataView).Table;
                  }
                  if( dataTable != null )
                  {
                  	// list box should only show only show columns which
                     // will work with the particular DBControl
	                  ColumnListBox columnListBox = new ColumnListBox(provider, dataTable, Convert.ToString(value));
                     // if descendent class have set LimitTypesTo appropriate value
                     WebControl wc = context.Instance as WebControl;
                     if( wc is DBWebMemo )
                     {
                        FLimitTypesTo.Clear();
         					FLimitTypesTo.Add(LimitTypesChar);
                        if( (wc as DBWebMemo).ValidColumnType == AcceptColumnType.actTextBlobAndString )
         						FLimitTypesTo.Add(LimitTypesStr);
                     }
                     if( LimitTypesTo.Count > 0 )
	                     for( int i = 0; i < LimitTypesTo.Count; i++ )
   	                  	columnListBox.LimitType.Add(LimitTypesTo[i]);
                     else if( ExcludeTypes.Count > 0 )
                     	for( int i = 0; i < ExcludeTypes.Count; i++ )
                        	columnListBox.ExcludeList.Add(ExcludeTypes[i]);
                     if( !columnListBox.InitList(Convert.ToString(value)))
                     {
						   	string NoMatchingFields = BdwResources.GetString("NoMatchingFields");
                     	throw new Exception(NoMatchingFields + wc.ToString());
                     }
   	               editorService.DropDownControl(columnListBox);
      	            int newColumnIndex = columnListBox.GetSelectedConnectionIndex();
         	         if (newColumnIndex >= 0 && newColumnIndex != columnListBox.OldConnectionIndex)
            	      {
               	   	for( int i = 0; i < columnListBox.Items.Count; i++ )
                  	   	if( i == newColumnIndex )
                     	   	value = columnListBox.Items[i].ToString();
	               	}
   	            }
               }
            }
            catch
            {
            	// TODO: what should happen here
            }
         }
         return value;
      }

      public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
      {
      	return UITypeEditorEditStyle.DropDown;
      }
   }

   public class MemoColumnPropEditor : ColumnNamePropEditor
   {
   	public MemoColumnPropEditor() : base()
      {
      	FLimitTypesTo.Clear();
      }
   }
   public class ImageColumnPropEditor : ColumnNamePropEditor
   {
      public const string LimitTypes = "System.Byte[]";
   	public ImageColumnPropEditor() : base()
      {
      	FLimitTypesTo.Clear();
         FLimitTypesTo.Add(LimitTypes);
      }
   }
   public class DateTimeColumnPropEditor : ColumnNamePropEditor
   {
      public const string LimitTypes = "System.DateTime";
   	public DateTimeColumnPropEditor() : base()
      {
      	FLimitTypesTo.Clear();
         FLimitTypesTo.Add(LimitTypes);
      }
   }

   public class BooleanColumnPropEditor : ColumnNamePropEditor
   {
      public const string LimitTypes1 = "System.Boolean";
      public const string LimitTypes2 = "System.String";
   	public BooleanColumnPropEditor() : base()
      {
      	FLimitTypesTo.Clear();
         FLimitTypesTo.Add(LimitTypes1);
         FLimitTypesTo.Add(LimitTypes2);
      }
   }

   public class LookupColumnNamePropEditor : ColumnNamePropEditor
   {
      public LookupColumnNamePropEditor() : base()
      {
      }

      protected override string GetTableName( WebControl wc )
      {
      	return (wc as IDBWebLookupColumnLink).LookupTableName;
      }

   }

	public class TableNamePropEditor : DBWebControlTypeEditor
  	{
  		public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
      {
      	if (context != null && context.Instance != null &&  context.Instance is WebControl)
         {
         	try
            {
            	IWindowsFormsEditorService editorService = (IWindowsFormsEditorService)
               provider.GetService(typeof(IWindowsFormsEditorService));
               if (editorService != null && context.OnComponentChanging())
               {
                  SetDataSource(context);
                  System.Data.DataSet dataSet = null;
                  if( dataSource != null )
                  {
                  	Object o = dataSource.GetDataSource(null);
                     if( o is DataSet )
                     	dataSet = (o as DataSet);
                     else if( o is DataTable )
                     	dataSet = (o as DataTable).DataSet;
                     else if( o is DataView )
                     	dataSet = (o as DataView).Table.DataSet;
                  }
                  if( dataSet != null )
                  {
	                  TableNameListBox tablesListBox = new TableNameListBox(provider, dataSet, Convert.ToString(value));
   	               editorService.DropDownControl(tablesListBox);
      	            int newTableIndex = tablesListBox.GetSelectedConnectionIndex();
         	         if (newTableIndex >= 0 && newTableIndex != tablesListBox.OldConnectionIndex)
            	      {
               	   	for( int i = 0; i < tablesListBox.Items.Count; i++ )
                  	   	if( i == newTableIndex )
                     	   	value = tablesListBox.Items[i].ToString();
	               	}
   	            }
               }
            }
            catch
            {
            	// TODO: what should happen here
            }
         }
         return value;
      }

      public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
      {
      	return UITypeEditorEditStyle.DropDown;
      }
   }

   public class DBWebSelectJpg : DBWebSelectFile
   {
   	protected override string Extension
      {
      	get
         {
	      	return "*.jpg";
         }
      }

      protected override string Filter
      {
      	get
         {
         	return BdwResources.GetString("ImageFilesFilter") + "|" + base.Filter;
         }
      }
   }
   public class DBWebSelectFile : UITypeEditor
   {
      protected virtual string Extension
      {
      	get
         {
	      	return "*.*";
         }
      }

      protected virtual string Filter
      {
      	get
         {
         	return BdwResources.GetString("AllFilesFilter");
         }
      }

  		public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
      {
         OpenFileDialog dialog = new OpenFileDialog();
         dialog.DefaultExt = Extension;
         dialog.Filter = Filter;
         if( dialog.ShowDialog() == DialogResult.OK )
         {
         	string fileName = dialog.FileName;
            string srcFileName = fileName;
            string targetFileName = null;

            int iLastIndex = fileName.LastIndexOf('\\');
            if( iLastIndex > 0 )
            {
               targetFileName = fileName.Substring(iLastIndex);
            	fileName = "." + fileName.Substring(iLastIndex);
            }
            else
					targetFileName = fileName;
            value = fileName;
            if( context.Instance is DBWebNavigator )
            {
            	DBWebNavigator navigator = (context.Instance as DBWebNavigator);
               if( !ClassUtils.IsEmpty(navigator.ImagesVirtualPath) )
               {
               	Borland.Data.Web.VirtualDirectory vDir = new Borland.Data.Web.VirtualDirectory("");
                  string sPath = vDir.FindPathForVirtualDir(navigator.ImagesVirtualPath);
                  if( !ClassUtils.IsEmpty(sPath) )
                  {
                  	targetFileName = sPath + targetFileName;
                     if( ! File.Exists(targetFileName) )
							{
			               string message = BdwResources.GetString("LocalIconRequired") + " " +
                        						sPath + ": " + BdwResources.GetString("CopyIconFile");
                        string caption = BdwResources.GetString("MissingImages");
			               MessageBoxButtons buttons = MessageBoxButtons.YesNo;
			               if( MessageBox.Show(message, caption, buttons) == DialogResult.Yes )
				            	File.Copy(srcFileName, targetFileName);
                     }
                  }
               }
            }
         }
         return value;
      }
      public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
      {
      	return UITypeEditorEditStyle.Modal;
      }
   }
   #endregion
   #region DataSourceEditor
   public class DataSourceEditor : UITypeEditor
   {
     	public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
      {
      	try
         {
         	IWindowsFormsEditorService editorService = (IWindowsFormsEditorService)
            provider.GetService(typeof(IWindowsFormsEditorService));
            if (editorService != null && context.OnComponentChanging())
            {
      			DataSourceListBox lb = new DataSourceListBox(provider, context.Container.Components, value, false);
               editorService.DropDownControl(lb);
               int newDSIndex = lb.GetSelectedConnectionIndex();
               if (newDSIndex >= 0 && newDSIndex != lb.OldIndex)
               	value = lb.GetSelectedObject(newDSIndex);
            }
         }
         catch
         {
         }
         return value;
      }
      public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
      {
      	return UITypeEditorEditStyle.DropDown;
      }
   }
   #endregion

   #region NoDataSourceEditor
   public class NoDataSourceEditor : UITypeEditor
   {
     	public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
      {
      	try
         {
         	IWindowsFormsEditorService editorService = (IWindowsFormsEditorService)
            provider.GetService(typeof(IWindowsFormsEditorService));
            if (editorService != null && context.OnComponentChanging())
            {
      			DataSourceListBox lb = new DataSourceListBox(provider, context.Container.Components, value, true);
               editorService.DropDownControl(lb);
               int newDSIndex = lb.GetSelectedConnectionIndex();
               if (newDSIndex >= 0 && newDSIndex != lb.OldIndex)
               	value = lb.GetSelectedObject(newDSIndex);
            }
         }
         catch
         {
         }
         return value;
      }
      public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
      {
      	return UITypeEditorEditStyle.DropDown;
      }
   }
   #endregion

	#region delegates and EventArgs
   	public class UpdateComponentEventArgs : EventArgs
      {
      	private System.ComponentModel.IComponent comp;
      	private Object O;
         public UpdateComponentEventArgs(System.ComponentModel.IComponent c,
                                              Object o)
      	{
         	O = o;
            comp = c;
         }
         public Object Object
         {
         	get
            {
            	return O;
            }
         }
         public System.ComponentModel.IComponent Component
         {
         	get
            {
            	return comp;
            }
         }
      }

     public delegate string OnComponentChangedEvent(object sender, UpdateComponentEventArgs ce);

	#endregion

}

