using System;
using System.Web;
using System.Xml;
using System.Net;
using System.Xml.Linq;
using System.Threading;
using StubCore.Entities;
using Newtonsoft.Json.Linq;
using StubCore.Plugins.Helpers;
using System.Collections.Generic;
using StubCore.Plugins.DataOperations;

namespace StubCore.Plugins.QueryOperations
{
    public class FlexQueryData
    {
        private string _profile;
        private string _transportType;
        private string _stream;
        private string _method;
        /*
        //public QDataOperations _qhelper = new QDataOperations();
        public ResponseData _response;

        private string _fileName;

        public FlexQueryData(string profileName, string file)
        {
            this._profile = profileName;
            this._fileName = file;

            if (!String.IsNullOrEmpty(profileName))
            {
                this._qhelper.SetProfile(profileName);
            }
        }

        /// <summary>
        /// Class constructor. Operate with flexible requests
        /// </summary>
        /// <param name="profileName">Name of current profile</param>
        /// <param name="type">Type of posted data</param>
        /// <param name="stream">Stream of posted data</param>
        /// <remarks>
        /// Last changed: 12.10.2015
        /// Author: Mikhael Aktsyzniy
        /// </remarks>
        public FlexQueryData(string profileName, string method, string type, string stream)
        {
            this._profile = profileName;
            this._transportType = this.IdentifyType(type);
            this._stream = stream;
            this._method = method;

            if (!String.IsNullOrEmpty(profileName))
            {
                this._qhelper.SetProfile(profileName);
            }

        }

        
        /// <summary>
        /// Initializing the process of request data validation and operations
        /// </summary>
        /// <returns>Response or error</returns>
        /// <remarks>
        /// Last changed: 18.10.2016
        /// Author: Mikhael Aktsyzniy
        /// </remarks>
        public OperationResponse InitResponse()
        {
            var _odata = new ODataResponse();
            var _files = new List<string>();

            switch (_transportType)
            {
                case "application/json":
                    _files = this.FindFilesJson();
                    break;
                case "application/x-www-form-urlencoded":
                    _files = this.FindFilesForm();
                    break;
                default:
                    _files = this.FindFilesXML();
                    break;
            }


            return this.ValidateResponse(_odata, _files)._opr;
        }

        /// <summary>
        /// Initializing the process of GET request data validation and operations
        /// </summary>
        /// <returns>Response or error</returns>
        /// <remarks>
        /// Last changed: 18.10.2016
        /// Author: Mikhael Aktsyzniy
        /// </remarks>
        public OperationResponse InitGetResponse()
        {
            var _odata = new ODataResponse();
            var _files = new List<string>()
            {
                { this._fileName }
            };

            return this.ValidateResponse(_odata, _files)._opr;
        }

        /// <summary>
        /// Validate response and send it
        /// </summary>
        /// <param name="_odata"></param>
        /// <param name="_files"></param>
        /// <returns>Response with HHTP Code</returns>
        public ODataResponse ValidateResponse(ODataResponse _odata, List<string> _files)
        {
            bool isNotEmpty = this._qhelper.ValidateProfileData(this._profile, _files);

            if (isNotEmpty)
            {
                OperationResponse _response = _qhelper.GetFileByRequest(_files);
                _odata.ResetEssense(_response);

                if (_response.isCompleted)
                {
                    if (this._method != "redirect")
                    {
                        switch (this._qhelper._profile.transportType)
                        {
                            case "json":
                                this._transportType = this._qhelper._profile.transportType;
                                this.SetJsonResponse(_response.message);
                                break;
                            default:
                                this._transportType = this._qhelper._profile.transportType;
                                this.SetXmlResponse(_response.message);
                                break;
                        }
                    }
                    else
                    {
                        this.SetRedirectResponse(_response.message);
                    }

                    _odata.SetMessage("The STUB is sending you greetings!");
                }

                if(_qhelper._profile.responseDelay > 0)
                {
                    var ms = _qhelper._profile.responseDelay * 1000;
                    Thread.Sleep(ms);
                }
                
            }
            else
            {
                _odata.SetMessage("Profile or profile files can not be found");
            }

            return _odata;
        }

        /// <summary>
        /// Parse the xml file-request what was received to find the name of file,
        /// what should be returned
        /// </summary>
        /// <returns>Name of file</returns>
        /// <remarks>
        /// Last changed: 13.10.2015
        /// Author: Mikhael Aktsyzniy
        /// </remarks>
        public List<string> FindFilesXML()
        {
            var doc = new XmlDocument();
            doc.LoadXml(this._stream);

            var nodeValues = new List<string>() {
                {"manuscript.xml"}
            };

            var manager = new XmlNamespaceManager(doc.NameTable);

            if (this._qhelper._profile.nameSpaces != null && this._qhelper._profile.nameSpaces.Count > 0)
            {
                foreach (TType nameSpace in this._qhelper._profile.nameSpaces)
                {
                    manager.AddNamespace(nameSpace.id, nameSpace.value);
                }
            }
            else
            {
                manager.AddNamespace("base", "base");
                manager.AddNamespace("b", "base");
                manager.AddNamespace("i", "http://www.w3.org/2001/XMLSchema-instance");
                manager.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
                manager.AddNamespace("v0", "http://insurancelab.accenture.com/AIL/v0.1/");
            }

            if (!this.FindManuscript(doc, manager))
            {
                nodeValues.Clear();
                foreach (string keyNode in this._qhelper._profile.xmlNodes)
                {
                    var node = doc.SelectSingleNode("//" + keyNode, manager);

                    if (node != null)
                    {
                        if (node.InnerText != null)
                        {
                            nodeValues.Add(node.InnerText);
                        }
                    }
                }
            }

            return nodeValues;
        }

        /// <summary>
        /// Parse the json file-request what was received to find the name of file,
        /// what should be returned
        /// </summary>
        /// <returns>Name of files</returns>
        /// <remarks>
        /// Last changed: 18.10.2016
        /// Author: Mikhael Aktsyzniy
        /// </remarks>
        public List<string> FindFilesJson()
        {
            var nodeValues = new List<string>();
            var jsonFile = JObject.Parse(this._stream);

            foreach (string keyNode in this._qhelper._profile.xmlNodes)
            {
                var keyValue = (string)jsonFile.SelectToken(keyNode);
                nodeValues.Add(keyValue);
            }

            return nodeValues;
        }

        /// <summary>
        /// Parse POST string what was received to find the name of file,
        /// what should be returned
        /// </summary>
        /// <returns>Name of files</returns>
        /// <remarks>
        /// Last changed: 21.10.2016
        /// Author: Mikhael Aktsyzniy
        /// </remarks>
        public List<string> FindFilesForm()
        {
            var nodeValues = new List<string>();
            var formRequest = HttpUtility.ParseQueryString(this._stream);

            foreach (string keyNode in this._qhelper._profile.xmlNodes)
            {
                var keyValue = formRequest[keyNode];

                if (!String.IsNullOrEmpty(keyValue))
                {
                    nodeValues.Add(keyValue);
                }

            }
            return nodeValues;
        }
        
        /// <summary>
        /// Parse type to select useful path of file name
        /// </summary>
        /// <param name="_type">Type of current file</param>
        /// <returns>Cleared file type. Ex: text/xml, text/json </returns>
        /// <remarks>
        /// Last changed: 08.10.2015
        /// Author: Mikhael Aktsyzniy
        /// </remarks>
        public string IdentifyType(string _type)
        {
            return _type.Split(';')[0];
        }

        /// <summary>
        /// Set JSON Response. Set results inside object
        /// </summary>
        /// <param name="fileResponse">File response</param>
        /// <remarks>
        /// Last changed: 20.10.2016
        /// Author: Mikhael Aktsyzniy
        /// </remarks>
        public void SetJsonResponse(string fileResponse)
        {
            this._response = new ResponseData() {
                _jsonResponse = JObject.Parse(fileResponse),
                _contentType = this._transportType + "; encoding='utf-8'",
                _statusCode = HttpStatusCode.OK
            };
                
        }

        /// <summary>
        /// Set XML Response. Set results inside object
        /// </summary>
        /// <param name="fileResponse">File response<</param>
        /// <remarks>
        /// Last changed: 20.10.2016
        /// Author: Mikhael Aktsyzniy
        /// </remarks>
        public void SetXmlResponse(string fileResponse)
        {
            var _fileResult = XElement.Parse(fileResponse);
            this._response = new ResponseData()
            {
                _xmlResponse = _fileResult,
                _contentType = this._transportType + "; encoding='utf-8'",
                _statusCode = HttpStatusCode.OK
            };

        }

        /// <summary>
        /// Set redirect response
        /// </summary>
        /// <param name="fileResponse">File response<</param>
        /// <remarks>
        /// Last changed: 20.10.2016
        /// Author: Mikhael Aktsyzniy
        /// </remarks>
        public void SetRedirectResponse(string fileResponse)
        {
            this._response = new ResponseData()
            {
                _redirectUrl = fileResponse,
                _statusCode = HttpStatusCode.Redirect
            };
        }

        /// <summary>
        /// Check if request is asking the manuscript file
        /// </summary>
        /// <param name="doc">Document request</param>
        /// <param name="manager">Namespaces list</param>
        /// <returns>Bool value</returns>
        public bool FindManuscript(XmlDocument doc, XmlNamespaceManager manager)
        {
            bool isManuscript = false;
            var node = doc.SelectSingleNode("//Session.setDocumentRq", manager);

            if (node != null && node.Attributes != null)
            {
                var nodeAttr = node.Attributes["document"];
                if(nodeAttr != null && nodeAttr.Value == "_abs")
                {
                    isManuscript = true;
                }
            }

            return isManuscript;
        }
        */
    }
}
