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

using System;
using System.Data;
using System.IO;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Design;
using System.Runtime.Serialization;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Borland.Data.Web
{

	#region Link interfaces
   public interface IDBWebDataLink
   {
     string TableName { get; set;}
     IDBDataSource DBDataSource { get; set;}
   }

   public interface IDBWebColumnLink : IDBWebDataLink
   {
   	string ColumnName { get; set;}
   }

   public interface IDBWebLookupColumnLink : IDBWebColumnLink
   {
   	string LookupTableName { get; set; }
      string DataTextField { get; set; }
      string DataValueField { get; set; }
   }
   #endregion Link interfaces

   #region Link classes
   public class DBWebDataLink : IDBWebDataLink
   {
   	protected string FTableName;
      protected IDBDataSource FDBDataSource;
      protected WebControl control;
      protected bool FDataBoundCalculated;
      protected bool FIsDataBound;


      public DBWebDataLink( WebControl AControl )
      {
      	control = AControl;
         FDBDataSource = null;
         FTableName = null;
         FDataBoundCalculated = false;
      	FIsDataBound = false;
      }
      string IDBWebDataLink.TableName
      {
      	get
         {
         	return FTableName;
         }
         set
         {
            if( CheckTableName(value) )
            {
            	if( FTableName != value )
         			FDataBoundCalculated = false;
         		FTableName = value;
            }
         }
      }
      IDBDataSource IDBWebDataLink.DBDataSource
      {
      	get
         {
         	return FDBDataSource;
         }
         set
         {
            if ( (value == null && FDBDataSource == null) ||
                 (value == FDBDataSource) )
            	return;
            if( value == null && FDBDataSource != null )
            {
               FDBDataSource.RemoveControl(control);
            }
            FDataBoundCalculated = false;
         	FDBDataSource = value;
            if( FDBDataSource != null )
            {
            	SetChangedValues();
            }
         }
      }

      public void ClearLoading( )
      {
         if( control.Page.Session[DBWebConst.sLoading] == null )
         	return;
      	control.Page.Session.Remove(DBWebConst.sLoading);
      }

      public void CheckRequestID( NameValueCollection postCollection)
      {
         // check to make sure the Page's Request Id is correct;
         // it will be incorrect if user hit Back Page, or if requests
         // were fired before response was returned.
         // -------------------------------------------
      	if( control.Page.Session[DBWebConst.sLoading] != null )
         	return;
			control.Page.Session[DBWebConst.sLoading] = true;
         int iRequestID = -1;
         int iSessionID = -1;
         object PageSessionId = postCollection[DBWebConst.sRequestID];
         if( PageSessionId != null )
         	iRequestID = Convert.ToInt32(PageSessionId);
         object SessionId = control.Page.Session[control.Page.Session.SessionID];
         	iSessionID = Convert.ToInt32(SessionId);
         if( iRequestID > -1 )
	         if( iRequestID != iSessionID )
   	      	control.Page.Response.Redirect(control.Page.Request.Url.AbsoluteUri);
         control.Page.Session[control.Page.Session.SessionID] = iRequestID +1;
      }

      protected void SetChangedValues( )
      {
      	FDBDataSource.AddControl(control);
         if( ClassUtils.IsDesignTime(control.Page) )
         	return;
      	ClearLoading();
         if( IsDataBound )
        	{
         	NameValueCollection postCollection = control.Page.Session[FTableName + DBWebConst.sDBWPostCollection] as NameValueCollection;
            if( postCollection != null )
            {
	         	if( (FDBDataSource as IDBPostStateManager).SetChangedValues(control.Page, postCollection, FTableName, control) )
               	WriteRowInfo();
               control.Page.Session.Remove(FTableName + DBWebConst.sDBWPostCollection);
            }
            else if( control.Page.Session[FTableName + DBWebConst.sCurrentRowIndex] == null )
            	WriteRowInfo();
         }
      }

      private bool CheckTableName(string tableName)
      {
         if( ClassUtils.IsEmpty(tableName) )
         	return true;
         if( FDBDataSource == null )
         	return true;
      	DataTable table = GetTable(tableName);
         if( table != null )
         {
         	if( table.TableName == tableName )
            	return true;
         }
         throw new Exception(BdwResources.GetString("InvalidTable") );
      }

      protected DataTable GetTable(string tableName)
      {
         if( ClassUtils.IsEmpty(tableName) )
         	return null;
      	if( FDBDataSource == null )
         	return null;
         Object o = FDBDataSource.GetDataSource(control.Page);
         DataSet ds = null;
         if( o is DataSet )
         	ds = o as DataSet;
         else if( o is DataView )
         	ds = (o as DataView).Table.DataSet;
         else if( o is DataTable )
         	ds = (o as DataTable).DataSet;
         if( ds != null )
         {
         	for( int i = 0; i < ds.Tables.Count; i++ )
            {
            	if( ds.Tables[i].TableName == tableName )
               {
               	return ds.Tables[i];
               }
            }
            return null;
         }
         return null;
      }

      public virtual bool IsDataBound
      {
      	get
         {
      		if( FDBDataSource == null || GetTable(FTableName) == null )
         		return false;
            return true;
         }
      }
     	public virtual bool DataSourceHasDelta(Page page)
      {
      	if( ClassUtils.IsDesignTime(page) || !IsDataBound )
         	return false;
         return FDBDataSource.HasDelta(page, FTableName);
      }

      public void AddToSession( string tableName, string sKey, string sValue )
      {
      	NameValueCollection nvc = control.Page.Session[tableName + DBWebConst.sDBWPostCollection] as NameValueCollection;
         if( nvc != null )
         {
         	nvc.Add(sKey, sValue);
            control.Page.Session[tableName + DBWebConst.sDBWPostCollection] = nvc;
         }
      }


      protected void WriteRowInfo()
      {  // only called when IsDataBound is true
			if( !ClassUtils.IsDesignTime(control.Page) )
			{
            int iCurrentRow = FDBDataSource.GetCurrentRow(control.Page, FTableName);
            int iRowCount = FDBDataSource.GetRowCount(control.Page, FTableName);
            int iFirstParentRow = (FDBDataSource as IDBPostStateManager).GetFirstParentRow(control.Page, FTableName);
            int iParentRow = (FDBDataSource as IDBPostStateManager).GetParentRow(control.Page, FTableName);
         	control.Page.Session[FTableName + DBWebConst.sCurrentRowIndex] = Convert.ToString(iCurrentRow);
				control.Page.Session[FTableName + DBWebConst.sRowCount] = Convert.ToString(iRowCount);
            control.Page.Session[FTableName + DBWebConst.sParentRow] = Convert.ToString(iParentRow);
            control.Page.Session[FTableName + DBWebConst.sFirstParentRow] = Convert.ToString(iFirstParentRow);
            control.Page.Session[FTableName + DBWebConst.sLastRow] = Convert.ToString(-1);
         	int iRequestId = Convert.ToInt32(control.Page.Session[control.Page.Session.SessionID]);
	         control.Page.RegisterHiddenField(DBWebConst.sRequestID, Convert.ToString(iRequestId));
			}
      }

		public void LoadPostData(string postDataKey, NameValueCollection postCollection)
      {  // for performance: only first control needs to set postCollection data
         if( control.Page.Session[FTableName + DBWebConst.sDBWPostCollection] != null )
         	return;
         CheckRequestID(postCollection);
         NameValueCollection stateCollection = new NameValueCollection();
         if( postDataKey == control.ID )
         {
   	      for(int i = 0; i < postCollection.Count; i++ )
            {
               string sKey = postCollection.GetKey(i);
               string sValue = postCollection.Get(i);
               stateCollection.Add(sKey, sValue);
            }
            control.Page.Session.Add(FTableName + DBWebConst.sDBWPostCollection, stateCollection);
         }
      }
   }

   public class DBWebColumnLink : DBWebDataLink, IDBWebColumnLink
   {
   	protected string FColumnName;

      public DBWebColumnLink(WebControl control): base(control)
      {
      }

      private bool CheckColumnName(string columnName)
      {
         DataTable table;
         if( ClassUtils.IsEmpty(columnName) )
         	return true;
      	if( !base.IsDataBound )
         	return true;
         table = GetTable(FTableName);
         if( table != null )
         {
         	DataColumnCollection columns = table.Columns;
	         if( columns != null )
   	      {
      	   	for( int i = 0; i < columns.Count; i++ )
         	   	if( columns[i].ColumnName == columnName )
            	   	return true;
            	throw new Exception(BdwResources.GetString("InvalidColumn"));
            }
         }
         return false;
      }

      string IDBWebColumnLink.ColumnName
      {
      	get
         {
         	return FColumnName;
         }
         set
         {
            if( CheckColumnName(value) )
            {
         		FColumnName = value;
               FDataBoundCalculated = false;
            }
         }
      }
      public override bool IsDataBound
      {
      	get
         {
            if( FDataBoundCalculated )
            	return FIsDataBound;
            // for performance, hold onto IsDataBound so there's no need to recalc each time
      		if( !base.IsDataBound ||
            			ClassUtils.IsEmpty(FColumnName) )
         		FIsDataBound = false;
            else
            {
            	FDataBoundCalculated = true;
	            Object o = FDBDataSource.GetTableOrView(control.Page, FTableName);
               FIsDataBound = o != null;
            }
	         return FIsDataBound;
         }
      }

      public void LoadCalendarColumn(NameValueCollection stateCollection)
      {
         if( stateCollection["__EVENTTARGET"] == control.ID && stateCollection["__EVENTARGUMENT"] != null )
         {
            string daysString = stateCollection["__EVENTARGUMENT"];
            if( daysString.StartsWith("V") )   // { do not localize }
            	daysString = daysString.Substring(1);
            string baseDate = BdwResources.GetString("BaseDate");

            DateTime newValue = DateTime.Parse(baseDate).AddDays(int.Parse(daysString));
            // the control's tableName/ColumnName information need be sent
            // to DBDataSource, as well as the current value to check if it has
            // changed.
            AddToSession(FTableName, control.ID, newValue.ToString() );
         }
      }
    }

   public class DBWebLookupColumnLink : DBWebColumnLink, IDBWebLookupColumnLink
   {
    	private string FLookupTableName;
    	private string FDataTextField;
    	private string FDataValueField;

      public DBWebLookupColumnLink(WebControl control): base(control)
      {
      }

      string IDBWebLookupColumnLink.LookupTableName
      {
      	get
         {
         	return FLookupTableName;
         }
         set
         {
         	FLookupTableName = value;
         }
      }
      string IDBWebLookupColumnLink.DataTextField
      {
      	get
         {
         	return FDataTextField;
         }
         set
         {
         	FDataTextField = value;
         }
      }
      string IDBWebLookupColumnLink.DataValueField
      {
      	get
         {
         	return FDataValueField;
         }
         set
         {
         	FDataValueField = value;
         }
      }
      public override bool IsDataBound
      {
      	get
         {
         	if( !base.IsDataBound ||
	            	ClassUtils.IsEmpty(FLookupTableName) ||
   	         	ClassUtils.IsEmpty(FDataTextField) )
      			return false;
				return true;
         }
      }
   }
   #endregion Link classes


   #region WebControlCollection
   public class DBWebControlCollection : ArrayList
   {
		public int Add(WebControl o)
		{
			return base.Add(o);
		}
		public new WebControl this[int index]
		{
			get
			{
				return base[index] as WebControl;
			}
			set
			{
				base[index] = value as WebControl;
			}
		}
   }
	#endregion


   #region EventArgsAndDelegates
   public class OnErrorEventArgs: EventArgs
   {
   	private ArrayList FErrors;
      private ArrayList FWarnings;
      private DataSet FDataSet;
      public OnErrorEventArgs(DataSet ds, ArrayList errors, ArrayList warnings): base()
      {
      	FErrors = errors;
         FWarnings = warnings;
         FDataSet = ds;
      }
      public DataSet DataSet
      {
      	get
         {
	      	return FDataSet;
         }
      }
      public ArrayList Errors
      {
      	get
         {
         	return FErrors;
         }
      }
   }
   public class OnScrollEventArgs : EventArgs
   {
   	private int FCurrentRow;
      private int FPriorRow;
      private string FTableName;
		public OnScrollEventArgs( String tableName, int currentRow, int priorRow ) : base()
		{
			FCurrentRow = currentRow;
         FTableName = tableName;
         FPriorRow = priorRow;
		}

		public int CurrentRow
		{
			get
			{
         	return FCurrentRow;
			}
		}
		public int PriorRow
		{
			get
			{
         	return FPriorRow;
			}
		}
      public string TableName
      {
      	get
         {
         	return FTableName;
         }
      }
   }
	public class WebControlEventArgs : EventArgs
	{
   	private DataSet FDataSet;
      public WebControlEventArgs(DataSet dataSet): base()
      {
      	FDataSet = dataSet;
      }
      public DataSet DataSet
      {
      	get
         {
         	return FDataSet;
         }
      }
	}

   public class DBWebButtonClickArgs : EventArgs
	{
   	private string FButtonName;
      private object FTable;
      public DBWebButtonClickArgs(string button, object table): base()
      {
      	FButtonName = button;
         FTable = table;
      }
      public object TableOrView
      {
      	get
         {
         	return FTable;
         }
      }
      public string ButtonName
      {
      	get
         {
         	return FButtonName;
         }
      }
	}

 	public delegate void DBWebNavigatorEvent(Object sender, DBWebButtonClickArgs e);
	public delegate void WebControlEvent(Object sender, WebControlEventArgs e);
	public delegate void OnScrollEvent(Object sender, OnScrollEventArgs e);
	public delegate void OnErrorEvent(Object sender, OnErrorEventArgs e);
   #endregion
}
