using System;
using System.Data;
using System.Data.SqlClient;
using System.Threading;
using System.Timers;
using edu.jhu.Cas.Jobs;

namespace edu.jhu.Cas.Util {
	public class CasJobsException:Exception{
		public CasJobsException(string s):base(s){}
        public CasJobsException(string message, Exception inner) : base(message, inner) { }
	}
	public abstract class QueryObject {
        protected bool IsComplete;
		public int TimeOut;
		public Exception Error;
		public DataSet dataSet;
		public long Rows;
		public Server VirtualHost;
		public string CreatedTable;
        public bool cancelled = false;
		internal System.Timers.Timer TimeoutTimer;
		internal Job job;
		internal string cString;
		internal int MemLimit = ID.QUERY_MEM_CAP;
		internal Thread queryThread,mainThread;
		internal CasJobsAdmin jAdmin = new CasJobsAdmin();
		internal long serviceID = ID.SERVICE_ID;
		public int QueryMemoryLimit {
			get {
				return MemLimit;
			}
		}
	
		public virtual void Run() {
			TimeoutTimer = new System.Timers.Timer((double)TimeOut);
			TimeoutTimer.Elapsed+=new ElapsedEventHandler(TimerCancel);
			TimeoutTimer.AutoReset = false;
			TimeoutTimer.Enabled = true;
			TimeoutTimer.Start();
		}
		//for timeouts
		public virtual void TimerCancel(Object state,ElapsedEventArgs args) {
            Error = new TimeoutException("Query exceeds queue time.  Please revise your query or use a longer queue.");
            doCancel();
		}
		//for users
		public virtual void Cancel(Object state,ElapsedEventArgs args) {
			if(Error == null) Error = new TimeoutException("Cancellation complete.");
            doCancel();
		}
        private void doCancel() {
            cancelled = true;
            try {
                jAdmin.CompleteCancel(job.WebServicesID, job.JobID, Error.Message, job.Created_Table);
            }
            catch { }
            try { mainThread.Interrupt(); }
            catch { }
            try { queryThread.Abort(); }
            catch { }
            
        }
        protected void CreateMydbTable(string tableName, SqlDataReader srcReader, SqlCommand mydbCom) {
            string qry = "CREATE TABLE " + tableName + " ( ";
            DataTable schema = srcReader.GetSchemaTable();
            int count = schema.Columns.Count;
            string colname = null;
            for (int x = 0; x < srcReader.FieldCount; x++) {
                colname = srcReader.GetName(x);
                if (colname == null || colname.Length == 0)
                    throw new CasJobsException("Cannot determine name of column number " + x + " in the select clause of your query.  Please give this column an explicit name and try again.");
                qry += "[" + colname + "] ";
                qry += Swizle(srcReader.GetDataTypeName(x));
                if (srcReader.GetDataTypeName(x).ToLower().StartsWith("binary")) {
                    // need to grab the size from the schema - pity the schema does not have the correct type  the we could just use that.
                    qry += "(" + schema.Rows[x]["ColumnSize"] + ")";
                }
                if (x < (srcReader.FieldCount - 1)) qry += ",";
            }
            qry += ")";
            mydbCom.CommandText = qry;
            mydbCom.ExecuteNonQuery();
        }
        protected bool IsQuick() {
            //int lowestQueue = SqlFactory.select("select min(estimate) 
            string q = "select min(queue) from servers where target like '" + job.Target + "'";
            int lowQ = (int)SqlFactory.scalar(q);
            return lowQ == job.Estimate;
        }
        /// Decimal casues some problems need to replace with real
        protected string Swizle(string TypeName) {
            if (TypeName.ToUpper().StartsWith("DECIMAL")) return "real";
            if (TypeName.ToUpper().StartsWith("REAL")) return "float";
            //if (TypeName.ToUpper().StartsWith("VARCHAR")) return "text";
            //if (TypeName.ToUpper().StartsWith("NVARCHAR")) return "ntext";
            //if (TypeName.ToUpper().StartsWith("NTEXT")) return "ntext";
            //if (TypeName.ToUpper().StartsWith("TEXT")) return "text";
            return TypeName;
        }
	}
}
