using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using log4net;
using Newtonsoft.Json;
using OpenCvSharp.CPlusPlus;
using YSoft.Rqamfp.Camera;
using Size = DbModel.DB.Model.Size;

namespace YSoft.Rqamfp.REST
{
    public class Attributes
    {
        public bool Operate { get; set; }
        public Size FSize { get; set; }
        public string Tid { get; set; }
        public uint Port { get; set; }
    }
    
    public class CreateRequest
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(CreateRequest));
        private static bool SendPostRequest(WebRequest request, string jsonPostString)
        {
            request.Method = "POST";
            request.ContentType = "application/JSON";
            var encoding = new UTF8Encoding();
            byte[] bytes = encoding.GetBytes(jsonPostString);
            request.ContentLength = bytes.Length;
            using (var requestStream = request.GetRequestStream())
            {
                requestStream.Write(bytes, 0, bytes.Length);
            }
            var response = (HttpWebResponse)request.GetResponse();
            var status = response.StatusCode;
            if (status != HttpStatusCode.OK)
                return false;
            log.Info("Returned status code: " + status);
            return true;
        }

        public static bool IsCameraCalibrated(int port) {
            if (Camera.Camera.ImageProcessingServer == null)
            {
                log.Warn("Address for Image Processing server is empty, cannot proceed");
                return false;
            }
            var request = WebRequest.Create("http://" + Camera.Camera.ImageProcessingServer + "/api/v1/improc/iscalibrated?port="+port);
            request.Method = "GET";
            request.ContentType = "application/x-www-form-urlencoded";
            var response = (HttpWebResponse)request.GetResponse();
            var status = response.StatusCode;
            if (status != HttpStatusCode.OK)
                return false;
            log.Debug("Returned status code: " + status);
            //return response;
            var encoding = Encoding.ASCII;
            var ResponseString = string.Empty;
            try
            {
                using (var reader = new StreamReader(response.GetResponseStream(), encoding))
                {
                    ResponseString = reader.ReadToEnd();
                }
            }
            catch (Exception ex)
            {
                log.Error("During reading of image evaluation response poped out an error", ex);
                return false;
            }
            try {
                return Convert.ToBoolean(ResponseString);
            } catch (Exception e) {
                log.Warn("Error occured during parsing to boolean",e);
                return false;
            }
        }

        public static string SendEvaluatingImage(string desired, Mat source, int port, EvaluationMode mode, EvaluationType type, JobSelection selection = JobSelection.None)
        {
            if (Camera.Camera.ImageProcessingServer == null)
            {
                log.Warn("Address for Image Processing server is empty, cannot proceed");
                return null;
            }
            var request = WebRequest.Create("http://" + Camera.Camera.ImageProcessingServer + "/api/v1/improc/evaluate?mode="+mode+"&type="+type+"&desired=" + desired + "&port=" + port + "&jobSelection=" + selection);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            byte[] bytes = source.ToBytes();
            request.ContentLength = bytes.Length;
            using (var requestStream = request.GetRequestStream())
            {
                requestStream.Write(bytes, 0, bytes.Length);
            }
            var response = (HttpWebResponse)request.GetResponse();
            var status = response.StatusCode;
            if (status != HttpStatusCode.OK)
                return string.Empty;
            log.Debug("Returned status code: " + status);
            //return response;
            var encoding = Encoding.ASCII;
            var jsonString = string.Empty;
            try
            {
                using (var reader = new StreamReader(response.GetResponseStream(), encoding))
                {
                    jsonString = reader.ReadToEnd();
                }
            }
            catch (Exception ex)
            {
                log.Error("During reading of image evaluation response poped out an error", ex);
                return null;
            }
            return jsonString;
        }

        public static bool SendCameraCalibrationPoints(List<Point2f> points, int mfd, string server)
        {
            var request = WebRequest.Create("http://" +server+ "/api/v1/improc/calibrate?port=" + RestServer.Instance.Port +"&mfd="+mfd);
            var jsonPostString = JsonConvert.SerializeObject(points);
            return SendPostRequest(request, jsonPostString);
        }

        public static bool EnableCoorSending(bool perm, string ip, string tid, Size screen, string http)
        {
            var Att = new Attributes() { Operate = perm, FSize = screen, Tid = tid, Port = RestServer.Instance.Port};
            log.Info("Sendind data to terminal server with IP: "+ip+" with Operate: "+Att.Operate);
            try
            {
                ServicePointManager.ServerCertificateValidationCallback = (o, certificate, chain, errors) => true;
                var request = WebRequest.Create(http +"://"+ip+"/et/"+tid+"/robot.ashx");
                var jsonPostString = JsonConvert.SerializeObject(Att);
                return SendPostRequest(request, jsonPostString);
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed to send request\n" + e.Message);
                return false;
            }
        }
    }
}
