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

using System;
using System.IO;
using System.Collections;
using System.Collections.Specialized;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Resources;
using System.Data;

namespace Borland.Data.Web
{

	public enum ImageType
	{
   	itNone,
		itJpg,
		itPng,
		itGif,
		itBmp
   }

	/// <summary>
	/// Borland DBWeb Utility Classes
	/// </summary>

#region Consts
  // { Do Not Localize any of these consts}
   public class DBWebConst
   {
		public const string sCurrentRowIndex = "RowIndex";
		public const string sRowCount = "RowCount";
      public const string sFirstParentRow = "FirstParentRow";
      public const string sParentRow = "ParentRow";
      public const string sLastRow = "LastRow";
		public const string sNextText = "Next";
		public const string sPrevText = "Prev";
		public const string sFirstText = "First";
		public const string sLastText = "Last";
		public const string sDeleteText = "Delete";
		public const string sInsertText = "Insert";
		public const string sApplyText = "ApplyToServer";
		public const string sRefreshText = "RefreshData";
		public const string sUndoText = "Undo";
		public const string sUndoAllText = "UndoAll";
      public const string Splitter = ":";
		public const string sDbxDelta = "DbxDelta";
		public const string sDbxDelete = "dbxDelete";
		public const string sDbxInsert = "dbxInsert";
		public const string sBeginRowCol = ":_:";
      public const string sEndRowCol = "_:_";
      public const string sBeginParentRows = "_pr_";
      public const string sEndParentRows = "_epr_";
   	public const string sRowColSplitter = ",";
      public const string sGridColumnID = ":_ctl";
      public const string sDBWebDataGrid = "DBWebDataGrid";
      public const string sErrorKey = "BorlandDBWebControlError_";
      public const string sDataSource = "DBWebControlDataSource";
      public const string sGridColumnCount = "_GridColumnCount";
      public const string sSetRow = "_SetCurrentRow";
      public const string sCancelChange = "_CancelChange";
      public const string sDeleteRow = "_DeleteRow";
      public const string sLastButtonSelected = "_LastButtonSelected";
      public const string sAutoGenerateColumns = "_AutoGenerateColumns";
      public const string sInvalidBoundColumns = "_InvalidBoundColumns";
      public const string sDBWPostCollection = "_PostCollection_";
      public const string sChangedRow = "_NewRow_";
      public const string sBorlandImageID = "borlandimageid";
      public const string sBorlandImageFile = "BorlandImageFile";
      public const string sLoading = "_LoadingStateChanges";
      public const string sRequestID = "_RequestID";
	  public const string sImageIndex = "_ImageIndex";
	  public const string sHardDeletes = "_UseHardDelete";
   }
#endregion

#region resources
     public class BdwResources
   {
     private static ResourceManager m_ResManager = null;

     static BdwResources()
     {
#if VSBUILD
		 m_ResManager = new ResourceManager("Borland.Data.Web.BdwResources", typeof(Borland.Data.Web.BdwResources) .Assembly);
#else
		 m_ResManager = new ResourceManager("BdwResources", typeof(Borland.Data.Web.BdwResources) .Assembly);
#endif
     }

     public static String GetString(String Key)
     {
       return m_ResManager.GetString(Key);
     }
   }
#endregion

	[AttributeUsage(AttributeTargets.All)]
	public class LocalizableDescriptionAttribute: DescriptionAttribute
	{
		private bool localized = false;

		public LocalizableDescriptionAttribute(string description): base(description)
		{
		}

		public override string Description
		{
			get
			{
				if (!localized)
				{
						string localizedDescription = BdwResources.GetString(DescriptionValue);
						if (localizedDescription != null)
							DescriptionValue = localizedDescription;
						// if localizedDescription is not found, still use DescriptionValue string.
						localized = true;
				}
				return DescriptionValue;
			}
		}
	}

	[AttributeUsage(AttributeTargets.All)]
	public class LocalizableCategoryAttribute : CategoryAttribute
	{
		private string description;

		public LocalizableCategoryAttribute(string key): base(key)
		{
		}

		protected override string GetLocalizedString(string value)
		{
			if (description == null)
				description = base.GetLocalizedString(value);
			if (description == null)
				description = BdwResources.GetString(value);
			if (description == null)
				description = value;
			return description;
		}
	}	


   #region Class and DataSet utils
   public class ClassUtils
   {

   	private ClassUtils()
      {
      	/// Private constructor prevents creation of this static class
      }


      public static bool IsEmpty(string Setting)
      {
      	return (Setting == null || Setting == "");
      }

      public static void SetFontProps(WebControl target, WebControl source)
      {
         target.Font.CopyFrom(source.Font);
      }
   	public static void SetControlProps(WebControl target, WebControl source)
      {
         target.BorderStyle = source.BorderStyle;
         target.BackColor = source.BackColor;
         target.BorderColor = source.BorderColor;
         target.BorderWidth = source.BorderWidth;
         target.ForeColor = source.ForeColor;
         SetFontProps(target, source);
      }
      public static void TruncatePanelWidth(Panel APanel, double iExtraPanelPixels)
      {
         if( iExtraPanelPixels >= 0 )
         {
            string sWidth = Convert.ToString(APanel.Width.Value - iExtraPanelPixels) + "px";
         	APanel.Width = Unit.Parse(sWidth);
         }
      }
      public static bool OutputErrors(Page page, HtmlTextWriter output, IDBWebDataLink IDataLink)
      {
         string warningHtml = null;
         string errorHtml = null;
         bool error = false;
         if( IDataLink.DBDataSource != null )
         {
            if((IDataLink.DBDataSource as IDBPageStateManager).GetErrors(page).Count > 0 )
            {
	         	if( (IDataLink.DBDataSource as DBWebDataSource).ErrorOption != ErrorHtmlOption.logWithErrorEvent )
               {
		            errorHtml = IDataLink.DBDataSource.GetErrorHtml(page, IDataLink.TableName);
   	      		output.Write(errorHtml);
               }
               error = true;
            }
            if((IDataLink.DBDataSource as IDBPageStateManager).GetWarnings(page).Count > 0 )
            {
	         	if( (IDataLink.DBDataSource as DBWebDataSource).ErrorOption != ErrorHtmlOption.logWithErrorEvent )
               {
		         	warningHtml = IDataLink.DBDataSource.GetWarningHtml(page, IDataLink.TableName);
         			output.Write(warningHtml);
               }
               error = true;
            }
            if( error )
            	(IDataLink.DBDataSource as IDBPageStateManager).DoOnError(page);
         }
         return error;
      }

      public static string GetInternalError(Page page, IDBWebDataLink IDataLink, Exception ex,
      							string ModuleName)
      {
      	(IDataLink.DBDataSource as IDBPostStateManager).SetCurrentRow(page, IDataLink.TableName, 0);
      	StringWriter sw = new StringWriter();
         HtmlTextWriter tw = new HtmlTextWriter(sw);
         tw.Write("<table width='100%' border=4><tr><td>");
         tw.Write(BdwResources.GetString("InternalError") + " " + ModuleName);
         tw.Write("</td></tr><tr><td>");
         tw.Write(ex.Message);
         tw.Write("</td></tr></table><p>");
         return sw.ToString();
      }


      public static void OutputOKButton(HtmlTextWriter output)
      {
      	Button button = new Button();
         button.Text =  BdwResources.GetString("OK");
         button.BorderWidth = Unit.Parse("4px");
         button.Width = Unit.Parse("48px");
         button.Height = Unit.Parse("32px");
         button.ID = "OK";
         output.Write("<p><center>");
         button.RenderControl(output);
         output.Write("<p></center>");
      }

      public static bool SameValue(string v1, string v2)
      {
      	if( v1 == null && v2 == null )
         	return true;
         else if( v1 == null || v2 == null )
         	return false;
         else return (v1 == v2);
      }

       #region Base Property Setting
		//	in cases where a derived control renders multiple ASP controls, the
      // class will not set the WebControl property.  In this case
      // appearance and behavior properties can be set on a control by
      // control basis.

      public static void SetAppearanceProperties( WebControl control, WebControl source )
      {
      	SetOuterAppearanceProperties(control, source);
         SetInnerAppearanceProperties(control, source);
         SetSizeProperties(control, source);
      }

      public static void SetSizeProperties( WebControl control, WebControl source )
      {
      	control.Width = source.Width;
      	control.Height = source.Height;
      }

      public static void SetOuterAppearanceProperties( WebControl control, WebControl source  )
      {
      	control.BorderColor = source.BorderColor;
      	control.BorderStyle = source.BorderStyle;
      	control.BorderWidth = source.BorderWidth;
      }
      public static void SetInnerAppearanceProperties( WebControl control, WebControl source  )
      {
      	control.ForeColor = source.ForeColor;
         control.BackColor = source.BackColor;
         control.Font.CopyFrom(source.Font);
      }
      public static void SetBehaviorProperties( WebControl control, WebControl source  )
      {
      	control.Visible = source.Visible;
      	control.Enabled = source.Enabled;
      	control.AccessKey = source.AccessKey;
      	control.TabIndex = source.TabIndex;
         control.ToolTip = source.ToolTip;
      	control.EnableViewState = source.EnableViewState;
      }
      #endregion Base Property Setting

      public static bool IsDesignTime(Page page)
      {
      	if( page == null )
         	return true;
         else if( page.Site != null )
         	return page.Site.DesignMode;
         return false;
      }
      #region KeyManagement
      // the KeyString contains the current of any parent tables, the row and col of
      // the current table, all preceded by sDbxDelta.  It is stored with a new value
      // in Page.Application to maintain changes associated with a particular session.
      // After ApplyChanges is successfully called these changes are removed.
      // Undo removes the last change, UndoAll removes all of them.
      public static string GetStartKeyName( string sKeyType, string sTableName, int iRow, int iCol)
      {
			return sKeyType + sTableName +
							DBWebConst.sBeginRowCol +
         				Convert.ToString(iRow) +
         				DBWebConst.sRowColSplitter +
         				Convert.ToString(iCol) +
                     DBWebConst.sBeginParentRows;
      }
		public static string GenKeyName(string sKeyType, string sTableName, int iRow, int iCol, string oldValue, ArrayList ParentRows)
   	{
      	string sKeyName;
         sKeyName = GetStartKeyName(sKeyType, sTableName, iRow, iCol );
         for( int i = 0; i < ParentRows.Count; i++ )
            sKeyName = sKeyName + Convert.ToString(ParentRows[i]) + DBWebConst.sRowColSplitter;
         if( oldValue != null )
         	return sKeyName + DBWebConst.sEndParentRows + oldValue;
         return sKeyName + DBWebConst.sEndParentRows;
      }

      // For performance, assume valid keys
      public static bool DoKeysMatch(string sKey1, string sKey2)
      {
         string s1 = sKey1.Substring(0, sKey1.IndexOf(DBWebConst.sEndParentRows) -1);
         string s2 = sKey2.Substring(0, sKey2.IndexOf(DBWebConst.sEndParentRows) -1);
         return s1 == s2;
      }

		public static string GenKeyName(string sKeyType, string sTableName, int iRow, int iCol, string oldValue, int[] ParentRows)
		{
      	string sKeyName;
         sKeyName = GetStartKeyName(sKeyType, sTableName, iRow, iCol );
         for( int i = 0; i < ParentRows.Length; i++ )
            sKeyName = sKeyName + Convert.ToString(ParentRows[i]) + DBWebConst.sRowColSplitter;
         if( oldValue != null )
         	return sKeyName + DBWebConst.sEndParentRows + oldValue;
         return sKeyName + DBWebConst.sEndParentRows;
		}

      // Given a specific Key from Page.Application.GetKey(index), extract
      // the current rows of any parent tables, and the row and col of the current
      // table so we know into which row/col to insert the changed value.
      // the return value is the array of Current Rows for all tables in the
      // dataset, so we know for which parent row a child row is referring
		public static ArrayList GetRowColFromKey(string sKey, out string TableName, out int iRow, out int iCol, out string sOldValue)
		{
         ArrayList Result = new ArrayList();
         int iRowColStart = sKey.IndexOf(DBWebConst.sBeginRowCol);
         int iDDL = DBWebConst.sDbxDelta.Length;
         TableName = sKey.Substring(iDDL, iRowColStart - iDDL);
         iRowColStart += DBWebConst.sBeginRowCol.Length;
         string sTemp = sKey.Substring(iRowColStart);
         int iStartParentRows = sTemp.IndexOf(DBWebConst.sBeginParentRows);
         int iSplitPos = sTemp.IndexOf(DBWebConst.sRowColSplitter);
         iRow = Convert.ToInt32(sTemp.Substring(0, iSplitPos));
         iCol = Convert.ToInt32(sTemp.Substring(iSplitPos+1,
         								iStartParentRows - (iSplitPos+1)));
         sTemp = sTemp.Substring(iStartParentRows + DBWebConst.sBeginParentRows.Length);
         iSplitPos = sTemp.IndexOf(DBWebConst.sRowColSplitter);
         while( iSplitPos > 0 )
         {
         	string sRow = sTemp.Substring(0, iSplitPos);
            Result.Add(Convert.ToInt32(sRow));
            sTemp = sTemp.Substring(iSplitPos + 1);
         	iSplitPos = sTemp.IndexOf(DBWebConst.sRowColSplitter);
            if( sTemp.StartsWith(DBWebConst.sEndParentRows) )
            	break;
         }
         int iEndParentRow = sKey.IndexOf(DBWebConst.sEndParentRows);
         if( iEndParentRow + 1 < sKey.Length )
           sOldValue = sKey.Substring(iEndParentRow + DBWebConst.sEndParentRows.Length);
         else
         	sOldValue = null;
         return Result;
		}
      #endregion KeyManagement
      public static string BindLookupControl(Page page, DBWebLookupColumnLink link, ListControl control)
      {
      	string CurrentValue = null;
         if( link == null )
         	return null;
         IDBWebLookupColumnLink ILink = (link as IDBWebLookupColumnLink);
         IDBDataSource dataSource = ILink.DBDataSource;
         if( link.IsDataBound )
         {
	         Object table = dataSource.GetTableOrView(page, ILink.LookupTableName);
            Object targetTable = dataSource.GetTableOrView(page, ILink.TableName);
            control.DataSource = table;
            if( ClassUtils.IsEmpty(control.DataValueField) )
            	control.DataValueField = control.DataTextField;
            if( !ClassUtils.IsEmpty(ILink.ColumnName ) )
            {
         		object o = (link as IDBWebColumnLink).DBDataSource.GetColumnValue(page,
            					(link as IDBWebColumnLink).TableName,
                           (link as IDBWebColumnLink).ColumnName);
               if( o != null )
                  CurrentValue = Convert.ToString(o);
            }
         }
         return CurrentValue;
      }

      public static int CurrentLookupIndex(ListControl control, string CurrentValue)
      {
      	ListItem item = control.Items.FindByText(CurrentValue);
         return control.Items.IndexOf(item);
      }

      public static bool PostCollectionHasValue(NameValueCollection postCollection,
      												string TableName, string value)
      {
      	if( postCollection[TableName + DBWebConst.Splitter + value] != null ||
      	      postCollection[TableName + DBWebConst.Splitter + value + ".x"] != null )
      		return true;
         return false;
      }

      public static string GetFullVirtualDirectory(string VirtualPathName)
      {
      	const string sHTTP = "http://";
         return sHTTP + System.Environment.MachineName + "/" + VirtualPathName + "/";
      }

      public static void AddStyleToPanel(Panel FPanel, CssStyleCollection Style)
      {
         IEnumerator keys = Style.Keys.GetEnumerator();
         while( keys.MoveNext() )
         {
            string key = Convert.ToString(keys.Current);
         	string value = Convert.ToString(Style[key]);
            FPanel.Style.Add(key, value);
         }
      }


   }
   #endregion


    #region DesignerUtil Class (DU)
    /// <summary>
    /// General purpose designer utility routines, lifted from BdpDesigners
    /// </summary>
    public class DU : System.Object
    {
        private DU()
        {
            /// Private constructor prevents creation of this static class
        }


        #region Component & Property Routines

        /// <summary>
        /// Returns true of the value is contained in the collection
        /// </summary>
        public static bool CollectionContains(IEnumerable collection, object value)
        {
            foreach (object obj in collection)
                if (obj == value)
                    return true;
            return false;
        }

        /// <summary>
        /// Returns an array of components
        /// </summary>
        public static IComponent[] GetComponents(IEnumerable collection, Type componentType)
        {
            ArrayList componentArray = new ArrayList();
            foreach (IComponent component in collection)
                if (componentType.IsInstanceOfType(component))
                    componentArray.Add(component);
            return (IComponent[])componentArray.ToArray();
        }

        /// <summary>
        /// Returns an array of components
        /// </summary>
        public static object[] GetComponentNames(IEnumerable collection, Type componentType, bool sorted)
        {
            ArrayList componentNames = new ArrayList();
            foreach (IComponent component in collection)
                if (componentType.IsInstanceOfType(component))
                    componentNames.Add(component.Site.Name);
            if (sorted)
                componentNames.Sort();
            return componentNames.ToArray();
        }

        /// <summary>
        /// Simple helper routine to get a property value
        /// </summary>
        public static object GetPropertyValue(object instance, string propertyName)
        {
            return TypeDescriptor.GetProperties(instance)[propertyName].GetValue(instance);
        }

        /// <summary>
        /// Simple helper routine to set a property value
        /// </summary>
        public static void SetPropertyValue(object instance, string propertyName, object value)
        {
        		TypeDescriptor.GetProperties(instance)[propertyName].SetValue(instance, value);
        }
        #endregion Component & Property Routines

    }
	#endregion DesignerUtil Class (DU)


   #region Debug

   public class Debug

   {   // quick and dirty debugging when client is remote
   	public static void LogString(Page page, string s)
      {
      	string fileName;
         if( !ClassUtils.IsDesignTime(page) )
         	fileName = page.Request.PhysicalApplicationPath + "debug.log";
         else
         	fileName = "c:\\debug.log";
      	LogString(s, fileName, false);
      }

      public static int Inspect(Object o)
      {
      	if( o is DataView )
         {
         	int value = (o as DataView).Count;
            if( value != (o as DataView).Table.Rows.Count )
            	value = (o as DataView).Table.Rows.Count;
            return value;
         }
      	else if( o is DataTable )
         {
         	int value = (o as DataTable).Rows.Count;
            return value;
         }
         else if( o is DataSet )
         {
         	DataSet ds = o as DataSet;
            int value = -1;
            if( ds.Tables.Count > 0 )
         		value = (o as DataSet).Tables[0].Rows.Count;
            return value;
         }


         return -1;
      }
      
      public static void LogString(string s, string FileName)
      {
      	LogString(s, FileName, false);
      }
      
      public static void LogString(string s, string FileName, bool CreateNew)
      {
         StreamWriter sw;
      	if(CreateNew && File.Exists(FileName))
         	File.Delete(FileName);
         sw = File.AppendText(FileName);
         try
         {
         	sw.WriteLine(s);
         }
         finally
         {
            sw.Close();
         }
      }
   }
   #endregion

}
