using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Data.SqlClient;
using System.Web.Configuration;

using net.ivoa.data;
using net.ivoa.VOTable;

using edu.jhu.Cas.Util;
using edu.jhu.Cas.Jobs;
using edu.jhu.Cas.Users;

namespace net.ivoa.tools {
    /// <summary>
    /// Summary description for TableImport.
    /// </summary>
    public class TableImport : System.Web.UI.Page {
        protected bool doSigma = false, enableFormatType = false, showinit = true;
        protected int MaxSize;
        protected string message;
        private int DataType, ImportType, FormatType, DataFormat;
        private string DataBoxText, FTPBoxText;
        protected HtmlInputFile httpBox;
        private double sigma;
        protected double estSize;
        protected string separator;
        protected short step;
        protected long rowsLoaded;
        protected string totalTime, tableName;
        protected string[] tables;
        protected long wsid;
        protected bool newTable = false;
        protected const long MAX_PASTE_CHARS = 2000, MAX_VOTABLE = 1024 * 1024, MAX_DATASET = 1024 * 1024;

        private void UploadText(string data) {
            //csvwrapper is from the DataWrapper package from OSQ
            CSVWrapper csvw = CSVWrapper.Reader2CSVWrapper((new StringReader(data)));
            UploadWrapper(csvw);
        }

        public void DoHTTPUpload() {
            DateTime ts = DateTime.Now;
            if (httpBox.PostedFile.FileName == null || httpBox.PostedFile.FileName == "") throw new Exception("Please select a file and try again.");
            if ((httpBox.PostedFile.ContentLength / 1000) > MaxSize) throw new Exception("This file cannot be imported because it is too large.");

            string cstring = (new CasUsers()).MyDBServerObject(wsid).ConnectionString;
            CSVDataReader csvr = new CSVDataReader(httpBox.PostedFile.InputStream, 1000);

            SqlCommand com = new SqlCommand();
            com.Connection = new SqlConnection(cstring);
            com.Connection.Open();
            com.CommandText = csvr.GetCreateTableQry(tableName);

            SqlBulkCopy sbc = new SqlBulkCopy(com.Connection);
            sbc.BulkCopyTimeout = 0;
            sbc.BatchSize = 100000;
            sbc.DestinationTableName = tableName;

            try {
                if (newTable)
                    com.ExecuteNonQuery();
                sbc.WriteToServer(csvr);
                totalTime = (DateTime.Now - ts).TotalSeconds.ToString();
                message = "<div>Table import complete!</div><div>Total Time: " + totalTime + "</div>" +
             "<div>Size " + (httpBox.PostedFile.ContentLength / 1000) + " kB</div>";
            }
            finally {
                com.Connection.Close();
                com.Connection.Dispose();
                sbc.Close();
            }
        }


        private void UploadWrapper(DataWrapper dw) {
            string cstring = (new CasUsers()).MyDBServerObject(wsid).ConnectionString;
            SqlCommand com = new SqlCommand();
            com.Connection = new SqlConnection(cstring);
            com.Connection.Open();
            try {
                WholeTableUpload.LoadDataWrapper(dw, com,tableName,newTable);
            }
            finally {
                com.Connection.Close();
                com.Connection.Dispose();
            }
        }
        override protected void OnInit(EventArgs E) {
            edu.jhu.Cas.Web.WebUtils.CheckLoggedIn(Session, Response);
            HttpRuntimeSection htrs = (HttpRuntimeSection)ConfigurationManager.GetSection("system.web/httpRuntime");
            MaxSize = htrs.MaxRequestLength;
            wsid = (long)Session["USER"];
            MyDBJobs mjs = new MyDBJobs();
            tables = mjs.Tables(wsid);

            message = Request.Params["message"];
            if (Request.Params["NameBox"] != null && Request.Params["NameBox"] != "")
                tableName = Request.Params["NameBox"];
            else
                tableName = edu.jhu.Cas.Web.WebUtils.GetUniqueTableName(wsid);
            try {
                DataType = Request.Params["DataType"] != null ? int.Parse(Request.Params["DataType"]) : -1;
                FormatType = Request.Params["formatType"] != null ? int.Parse(Request.Params["formatType"]) : 0;
                DataFormat = Request.Params["DataFormat"] != null ? int.Parse(Request.Params["DataFormat"]) : 0;
                ImportType = Request.Params["ImportType"] != null ? int.Parse(Request.Params["importType"]) : 0;
                DataBoxText = Request.Params["DataBox"];
                FTPBoxText = Request.Params["ftpBox"];
                if (Request.Params["tableTypeDDL"] != null)
                    newTable = int.Parse(Request.Params["tableTypeDDL"]) == 0;
                if (!newTable && Request.Params["DataType"] != null)
                    tableName = Request.Params["tnameDDL"];
                sigma = Request.Params["sigmaBox"] != null && Request.Params["sigmaBox"].Length > 0 ? double.Parse(Request.Params["sigmaBox"]) : -1;
            }
            catch (FormatException fe) {
                message = fe.Message;
                return;
            }
            try {
                if (Request.Params["DataType"] != null) {
                    Import();
                    tables = mjs.Tables(wsid);
                    tableName = edu.jhu.Cas.Web.WebUtils.GetUniqueTableName(wsid);
                }
            }
            catch (Exception e) {
                message = e.ToString();
            }
        }
        protected void Import() {
            try {
                string name = tableName;
                if (name.IndexOf(".") > -1 || name.IndexOf(" ") > -1 || name.IndexOf(",") > -1)
                    throw new Exception("Please do not use the following characters in your table name: '.',',' or ' '");
                string data = null;
                if (ImportType == 0) {
                    data = DataBoxText;
                    if (data != null) data = data.Trim(new char[] { ' ', '\t', '\r', '\n' });
                    if (data.Length > MAX_PASTE_CHARS) throw new Exception("The pasted data received is too large and will not be processed.");
                }
                else if (ImportType == 1 && (DataType != 0)) {
                    if (httpBox.PostedFile.ContentLength > MAX_DATASET) throw new Exception("This file is " +
                        (httpBox.PostedFile.ContentLength / 1000) + " kB but the maximum size for this datatype is " + MAX_DATASET + " kB.  Import halted.");
                    data = (new StreamReader(httpBox.PostedFile.InputStream)).ReadToEnd();
                }
                if (name == null || name.Length == 0)
                    throw new Exception("You must provide a table name.");
                name = name.Trim();
                switch (DataType) {
                    case 0://CSV
                        if (ImportType == 0) {
                            UploadText(data);
                            message = "CSV Table successfully imported as " + name;
                        }
                        else
                            DoHTTPUpload();
                        break;
                    case 1://VOTABLE
                        XmlTextReader reader = new XmlTextReader(new StringReader(data));
                        try {
                            XmlSerializer serializer = new XmlSerializer(typeof(VOTABLE));
                            VOTABLE vot = (VOTABLE)serializer.Deserialize(reader);
                            try {
                                TABLEDATA d = vot.RESOURCE[0].TABLE[0].DATA.Item as TABLEDATA;
                                if (d.TR.Length < 1) throw new Exception("This votable is empty.");
                            }
                            catch { throw new Exception("Unknown error deserializing VOTABLE"); }
                            UploadWrapper(WrapperFactory.GetDataWrapper(vot));
                        }
                        catch {
                            // ok try the lax parser 
                            reader = new XmlTextReader(new StringReader(data));
                            LaxVotableParser lp = new LaxVotableParser(reader);
                            DataSet ds = lp.readAsDataSet();
                            UploadWrapper(WrapperFactory.GetDataWrapper(ds));
                        }
                        message = "VOTABLE Table successfully imported as " + name;
                        break;
                    case 2://dataset
                        XmlTextReader reader2 = new XmlTextReader(new StringReader(data));
                        XmlSerializer serializer2 = new XmlSerializer(typeof(DataSet));
                        DataSet votds = (DataSet)serializer2.Deserialize(reader2);
                        UploadWrapper(WrapperFactory.GetDataWrapper(votds));
                        message = "DataSet table successfully imported as " + name;
                        break;
                }
            }
            catch (Exception e) { message = e.Message; }
        }
    }
}