using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security;
using System.Web;
using BeWo.Service.Plugins;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;

using BeWo.Data;
using BeWo.Report;
using BeWo.Service.Security;

using DevExpress.XtraPrinting;
using DevExpress.XtraReports.UI;

using Page = System.Web.UI.Page;

namespace Host
{
    public partial class ReportView : Page
    {
        private Dictionary<string, object> slicedToken;
	    private AbstractReportCreator reportCreator;

	    protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                if (!SessionFacade.IsUserLoggedIn())
                    throw new SecurityException("Anmeldung erforderlich!");

				var report = CreateReport();
				var repxStream = new MemoryStream();

				report.PrintingSystem.SaveDocument(repxStream, new NativeFormatOptions { Compressed = true });

				var bytesToWrite = repxStream.ToArray();

				Response.OutputStream.Write(bytesToWrite, 0, bytesToWrite.Length);
            }
            catch (Exception ex)
            {
				Response.Write(ex.Message + "\n\n" + ex.StackTrace);
            }
        }
		//Änderungen ServiceCategoryAuswahl bei Quittierungsbeleg wieder einkommentieren + testen

        private XtraReport CreateReport()
        {
            var token = Request.Params["token"].Split(',')[0];
	        if (SecurityUtils.CheckToken(token))
            {
				slicedToken = SecurityUtils.sliceToken(Request.Params["token"].Split(',')[0], Request.Url.ToString());
	            reportCreator = GetReportCreator();

                var lType = Utils.EnumParse<ReportTypes>(Request.Params["type"]);

	            XtraReport report;
	            switch (lType)
                {
                    case ReportTypes.ServiceInvoice:
                        report = CreateServiceInvoiceReport();
						break;
                    case ReportTypes.Settlement:
						report = CreateSettlementReport();
						break;
                    case ReportTypes.ServiceOverviewSingleCustomer:
						report = CreateServiceOverviewSingleCustomerReport();
						break;
                    case ReportTypes.ServiceOverviewAllCustomers:
						return CreateServiceOverviewAllCustomersReport();
                    case ReportTypes.CustomerData:
						report = CreateCustomerDataReport();
						break;
                    case ReportTypes.ServiceRecordList:
						report = CreateServiceRecordListReport();
						break;
                    case ReportTypes.SupportConceptReport:
						report = CreateSupportConceptReport();
						break;
                    case ReportTypes.FLSReport:
						report = CreateFlsReport();
						break;
                    case ReportTypes.CustomerInvoice:
						report = CreateCustomerInvoiceReport();
						break;
                    case ReportTypes.AssessmentSheetReport:
						report = CreateAssessmentSheetReport();
						break;
					case ReportTypes.AdditionalServiceBookingReport:
						report = CreateAdditionalServiceBookingReport();
						break;
					case ReportTypes.EmployeeHourReport:
						report = CreateEmployeeHourReport();
						break;
					case ReportTypes.AuslastungReport:
						report = CreateAuslastungReport();
						break;
					case ReportTypes.Medikamentenverordnungsliste:
						report = CreateMediVerordnungslistenReport();
						break;
					case ReportTypes.MedikamentenverordnungslisteMitZusatzfeldern:
						report = CreateMediVerordnungslistenMZusatzfeldernReport();
						break;
					case ReportTypes.HistorischeMedikamentenverordnungsliste:
						report = CreateHistorischeMediVerordnungslistenReport();
						break;
					case ReportTypes.Kalender: // Wird nicht mehr benötigt
		                report = CreateTestReportKalender();
		                break;
					case ReportTypes.FinanceReport:
						report = CreateFinanceReport();
		                break;
                    case ReportTypes.Jahresbericht:
                        report = CreateJahresbericht();
                        break;
                    default:
						report = CreateQueryReport();
		                break;
                }
	            if (report != null && lType != ReportTypes.ServiceOverviewAllCustomers &&
	                lType != ReportTypes.ServiceInvoice)
	            {
		            if (report.Pages.Count == 0)
		            {
			            report.CreateDocument();
		            }
	            }
	            return report;
            }

            Response.Write("Session ist abgelaufen! Bitte erstellen Sie den Bericht erneut. Nach Erstellen des Berichts haben Sie 10 Min. Zeit diesen auszudrucken.");
            return new XtraReport();
        }

		private XtraReport CreateTestReportKalender()
	    {
			var abc = Request.Params["r"].Split('-');
			var rightsList = abc.Select(r => (UserRightType)Int32.Parse(r)).ToList();
			//employeeOid, viewType
			var datesList = new List<DateTime>();
			string datesString = Request.Params["d"];
			for (var i = 0; i < datesString.Length; i += 8)
			{
				var x = datesString.Substring(i, 8);
				datesList.Add(new DateTime(Convert.ToInt32(x.Substring(4, 4)), Convert.ToInt32(x.Substring(2, 2)), Convert.ToInt32(x.Substring(0, 2))));
			}

			var vt = (AppointmentViewType) int.Parse(Request.Params["vt"]);
			var s = DateTime.Parse(Request.Params["s"]);
			var e = DateTime.Parse(Request.Params["e"]);
			var employeeOid = long.Parse(Request.Params["eOid"]);
			return reportCreator.CreateKalenderReport(employeeOid, vt, s, e, datesList, rightsList);
	    }

	    private XtraReport CreateCustomerDataReport()
        {
            long customerOid = long.Parse(Request.Params["cOid"]);

			return reportCreator.CreateCustomerDataReport(customerOid);
        }

		private XtraReport CreateCustomerInvoiceReport()
        {
            long invoiceOid = long.Parse(Request.Params["ioid"]);

			return reportCreator.CreateCustomerInvoiceReport(invoiceOid);
        }

		private XtraReport CreateAssessmentSheetReport()
        {
            var customerOid = long.Parse(Request.Params["coid"]);
            var month = Int32.Parse(Request.Params["m"]);
            var year = Int32.Parse(Request.Params["y"]);

			return reportCreator.CreateAssessmentSheetReport(customerOid, month, year);
        }

		private XtraReport CreateAdditionalServiceBookingReport()
		{
			var addservregionOid = long.Parse(Request.Params["asroid"]);
			Monat month;
			Enum.TryParse(Request.Params["m"], out month);
			var year = Int32.Parse(Request.Params["y"]);


			return reportCreator.CreateAdditionalServiceBookingReport(addservregionOid, month, year);
		}

		private XtraReport CreateEmployeeHourReport()
		{
			long? employeeOid = null;
			if (Request.Params["eoid"] != null)
				employeeOid = long.Parse(Request.Params["eoid"]);
			long? teamOid = null;
			if (Request.Params["toid"] != null)
				teamOid = long.Parse(Request.Params["toid"]);
			int month = Int32.Parse(Request.Params["m"]);
			var year = Int32.Parse(Request.Params["y"]);

			bool splitTeams = Request.Params["t"] != null && Request.Params["t"] == "1";
			var start = new DateTime(year, month, 1);
			var end = start.AddMonths(1);
			return reportCreator.CreateEmployeeHourReport(employeeOid, teamOid, start, end, splitTeams);
		}

		private XtraReport CreateAuslastungReport()
		{
			long? employeeOid = null;
			if (Request.Params["eoid"] != null)
				employeeOid = long.Parse(Request.Params["eoid"]);
			long? teamOid = null;
			if (Request.Params["toid"] != null)
				teamOid = long.Parse(Request.Params["toid"]);
			int month = Int32.Parse(Request.Params["m"]);
			var year = Int32.Parse(Request.Params["y"]);

			bool splitTeams = Request.Params["t"] != null && Request.Params["t"] == "1";
			var start = new DateTime(year, month, 1);
			var end = start.AddMonths(1);
			return reportCreator.CreateAuslastungReport(employeeOid, teamOid, start, end, splitTeams);
		}

		private XtraReport CreateFlsReport()
        {
            String flsReportId = Request.Params["dcid"];
			String subType = Request.Params["subType"];

			return reportCreator.CreateFlsReport(flsReportId, subType);
        }

		private XtraReport CreateQueryReport()
        {
            var queryOid = long.Parse(Request.Params["qoid"]);
            var queryReportId = Request.Params["dcid"];

			return reportCreator.CreateQueryReport(queryOid, queryReportId);
        }

		private XtraReport CreateServiceInvoiceReport()
        {
            String dcIds = Request.Params["dcids"];
			long? invoiceBaseOid = null;
			if (Request.Params["ibid"] != null)
				invoiceBaseOid = long.Parse(Request.Params["ibid"]);
			
			return reportCreator.CreateServiceInvoiceReport(dcIds, invoiceBaseOid);
        }

		private XtraReport CreateServiceOverviewAllCustomersReport()
		{
			int month = int.Parse(this.Request.Params["month"]);
			int year = int.Parse(this.Request.Params["year"]);
			long orgaOid = long.Parse(this.Request.Params["orgaOid"]);
			long empOid = long.Parse(this.Request.Params["empOid"]);
			int startDay = int.Parse(this.Request.Params["start"]);
			int endDay = int.Parse(this.Request.Params["end"]);
			long? scOid = null;
		    if (Request.Params["scOid"] != null)
		        scOid = long.Parse(Request.Params["scOid"]);
		    


			return reportCreator.CreateServiceOverviewAllCustomersReport(month, year, orgaOid, empOid, scOid, startDay, endDay);
		}


		private XtraReport CreateServiceOverviewSingleCustomerReport()
        {
            long customerOid = long.Parse(Request.Params["cOid"]);
            int month = int.Parse(Request.Params["month"]);
            int year = int.Parse(Request.Params["year"]);
            long orgaOid = long.Parse(Request.Params["orgaOid"]);
            long empOid = long.Parse(Request.Params["empOid"]);
            int startDay = int.Parse(Request.Params["start"]);
            int endDay = int.Parse(Request.Params["end"]);
			long? scOid;
			if (Request.Params["scOid"] != null)
				scOid = long.Parse(Request.Params["scOid"]);
			else
				scOid = null;

			return reportCreator.CreateServiceOverviewSingleCustomerReport(customerOid, month, year, orgaOid, empOid, scOid, startDay, endDay);
        }

		private XtraReport CreateServiceRecordListReport()
        {
			long eOid = long.Parse(Request.Params["eOid"]);
			long cOid = long.Parse(Request.Params["cOid"]);
			long scOid = long.Parse(Request.Params["scOid"]);
			long cb2scOid = long.Parse(Request.Params["cb2scOid"]);

			string isLimitedParam = Request.Params["l"];
			bool isLimited = isLimitedParam != null;

			return reportCreator.CreateServiceRecordListReport(eOid, cOid, scOid, cb2scOid, isLimited, null);
        }

		private XtraReport CreateSettlementReport()
        {
            String dcId = Request.Params["dcid"];

			long? invoiceBaseOid = null;
			if (Request.Params["ibid"] != null)
				invoiceBaseOid = long.Parse(Request.Params["ibid"]);

			return reportCreator.CreateSettlementReport(dcId, invoiceBaseOid);
        }

		private XtraReport CreateSupportConceptReport()
        {
            long my = long.Parse(Request.Params["my"]);
            long arc = long.Parse(Request.Params["arc"]);
            long eOid = long.Parse(Request.Params["eOid"]);

            DateTime? appointedDate = null;
            Object obj = Request.Params["date"];
            if (obj != null)
            {
                DateTime dt = DateTime.MaxValue;
                DateTime.TryParse(obj.ToString(), out dt);
                appointedDate = dt;
            }

			return reportCreator.CreateSupportConceptReport(eOid, my == 1, arc == 1, appointedDate);
        }

		private XtraReport CreateMediVerordnungslistenReport()
		{
			var mvlOid = long.Parse(Request.Params["mvlOid"]);

			return reportCreator.CreateMediVerordListenReport(mvlOid);
		}

		private XtraReport CreateMediVerordnungslistenMZusatzfeldernReport()
		{
			var mvlOid = long.Parse(Request.Params["mvlOid"]);

			return reportCreator.CreateMediVerordListenMZfReport(mvlOid, true);
		}

		private XtraReport CreateHistorischeMediVerordnungslistenReport()
		{
			var mvlOid = long.Parse(Request.Params["mvlOid"]);

			return reportCreator.CreateMediVerordListenReport(mvlOid);
		}

		private XtraReport CreateFinanceReport()
		{
			DateTime? start = null;
			DateTime? end = null;

			String date = Request.Params["start"];

			if (!String.IsNullOrEmpty(date) && date.Length == 8)
			{
				DateTime dt;
				if (DateTime.TryParse(
					String.Format("{0}.{1}.{2}", date.Substring(0, 2), date.Substring(2, 2), date.Substring(4, 4)), out dt))
				{
					start = dt;
				}
			}
			date = Request.Params["end"];

			if (!String.IsNullOrEmpty(date) && date.Length == 8)
			{
				DateTime dt;
				if (DateTime.TryParse(
					String.Format("{0}.{1}.{2}", date.Substring(0, 2), date.Substring(2, 2), date.Substring(4, 4)), out dt))
				{
					end = dt;
				}
			}


			return reportCreator.CreateFinanceReport(start, end);
		}

        private XtraReport CreateJahresbericht()
        {
            int year = int.Parse(Request.Params["y"]);
            long? cbOid = null;
            if (Request.Params["cb"] != null)
                cbOid = long.Parse(Request.Params["cb"]);

            long? teamOid = null;
            if (Request.Params["t"] != null)
                teamOid = long.Parse(Request.Params["t"]);

            long? artOid = null;
            if (Request.Params["art"] != null)
                artOid = long.Parse(Request.Params["art"]);

            return reportCreator.CreateJahresberichtReport(year, cbOid, teamOid, artOid);
        }

		private AbstractReportCreator GetReportCreator()
		{
			String t = slicedToken["tenant"].ToString();
			AbstractReportCreator creator = null;
#if DEBUG

			
			//Kundennummern zum Testen nur noch in PluginLoader eintragen:
			t = PluginLoader.Tenant;


			String customerDllPath = HttpContext.Current.Server.MapPath(@"bin\" + t + "_reports.dll");
#else
			String customerDllPath = HttpContext.Current.Server.MapPath(@"Customer\" + t + "_reports.dll");
#endif
			if (File.Exists(customerDllPath))
			{
				var allTypes = Assembly.LoadFrom(customerDllPath).GetTypes();

				var reportCreator = allTypes.FirstOrDefault(i => typeof(AbstractReportCreator).IsAssignableFrom(i));
				if (reportCreator != null)
				{
					creator = Activator.CreateInstance(reportCreator) as AbstractReportCreator;
				}

			}

			if (creator == null)
				creator = new DefaultReportCreator();

			creator.Tenant = t;
			creator.ReportPath = customerDllPath;

#if DEBUG
			creator.TempPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"demo\temp");
#else

			creator.TempPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, t + @"\temp");
#endif


			return creator;
		}
    }
}