// Bilanzdruck
using craftsReport.Interfaces;
using System;
using System.Collections.Generic;

namespace craftsReport.modules
{
	public class rp1102_xbs : IReportModule, IReportModuleEvents
	{
		#region Members and Contructor

		private bool m_IsLastPage = false;
		private int m_ZeileMax;
		private string m_HeaderResourceName = "KopfDetail";
		private string m_LstNr = ""; // aktuelle Listennummer
		private int m_LfdNr = 0; // wenn nicht null, dann nur Teilauswertung
		private IReportRecord m_recMain = null;
		private IReportRecord m_recBila = null;
		private IReportRecord m_recAnfang = null;
		private IReportRecord m_recEnde = null;
		private bool m_AllePositionen = false;
		private bool m_NurSummen = false;

		public rp1102_xbs()
		{
		}

		enum ChildType { empty, summnodes, positions }

		#endregion

		#region IReportModule

		public IReportHost HostObject { set; get; }

		public bool Execute()
		{
			// Parameter Listennummer
			if (!HostObject.IsVar("pLstNr"))
            {
				HostObject.DefineVariable2("pLstNr", "u,4,0");
				HostObject.Set("pLstNr", "0003", false);
			}
			m_LstNr = HostObject.EvalString("$[pLstNr]");
			m_recMain = HostObject.DefineRecord("recMAIN", "Bilanzsteuerung", 0, 4, HostObject.EvalString(@"$[pLstNr<4]"));
			m_recBila = HostObject.DefineRecord("recBILA", "Bilanz", 0, 4, HostObject.EvalString(@"$[pLstNr<4]"));

			// Parameter Subroutine
			if (!HostObject.IsVar("pLfdNr"))
			{
				HostObject.DefineVariable2("pLfdNr", "N,8,0");
				HostObject.Set("pLfdNr", "0", false);
			}
			m_LfdNr = HostObject.EvalInt("$[pLfdNr]");
			if (m_LfdNr != 0)
            {
				m_recMain.Find(m_LfdNr.ToString().PadLeft(8));
            }

			// Reporttitel
			HostObject.DefineVariable2("mRepTitle", "c,250,0");
			HostObject.Set("mRepTitle", @"$[recMAIN.Text]", true);

			// Auswertungstungszeitraum
			m_recAnfang = HostObject.DefineRecord("recAnfang", "OPTIONEN", 0, 5, HostObject.EvalString(@" 6220"));
			m_recEnde = HostObject.DefineRecord("recEnde", "OPTIONEN", 0, 5, HostObject.EvalString(@" 6221"));

			// Filtertext generieren
			HostObject.DefineVariable2("mFilterText", "c,250,0");
			HostObject.Set("mFilterText", CalcFilterText(), false);

			// Sonstige Steuerung
			if (HostObject.IsVar("pAlle"))
				m_AllePositionen = HostObject.EvalBool("$[pAlle]");
			if (HostObject.IsVar("pSummen"))
				m_NurSummen = HostObject.EvalBool("$[pSummen]");

			// Beginn der Ausgabe
			HostObject.LoadAdditionalResources("/r");
			HostObject.PaperDefinition("PaperDefinition");
			HostObject.DefineVariable2("mFontDetail", "c,50,0");
			HostObject.Set("mFontDetail", "$[mFontDefault]", true);

			m_ZeileMax = HostObject.EvalInt("$[ZlMax]");
			HostObject.DokumentStart();
			HostObject.SeitenKopf();

			if (m_LfdNr != 0)
			{
				// Teilauswertung nur dieser Zweig
				if (!m_recMain.Eof)
				{
					HandleRecMain(false, "");
				}
			}
			else
			{
				// Auswertung gesamte Steuerung
				while (!m_recMain.Eof)
				{
					HandleRecMain(false, "");
				}
			}

			m_IsLastPage = true;
			HostObject.SeitenFuss();
			HostObject.DokumentEnde();
			return true;
		}

		#endregion

		#region IReportModuleEvents

		public void OnAfterPageStart()
		{
			HostObject.ProcessResource(m_HeaderResourceName);
			Tabulieren();
			/*
			if (HostObject.EvalInt("$[Seite]") == 1)
			{
			}
			else
			{
			}
			*/
		}

		public void OnBeforePageClose()
		{
			if (m_IsLastPage)
			{
				if ((m_ZeileMax) > HostObject.EvalInt("$[Zeile]"))
					HostObject.ProcessResource("Sterne");
			}
			/*
			else
			{
			}
			*/
		}

		public void OnAfterExecute(string szOutFileName)
		{
		}

		#endregion

		#region Internals

		bool HandleRecMain(bool bSilent, string bsParentPosNr)
        {
			switch (m_recMain.Get("PosTyp"))
            {
				case 1:
					return HandleSumme(bSilent, bsParentPosNr);
				case 2:
					return HandlePosition(bSilent, bsParentPosNr);
				default:
					return HandleText(bSilent, bsParentPosNr);
            }
        }

		bool HandleSumme(bool bSilent, string bsParentPosNr)
		{
			bool bResult = false;
			HostObject.VariablesPush();

			// save current position
			int nLfdNr = HostObject.EvalInt("$[recMAIN.LfdNr]");

			int nTiefe = HostObject.EvalInt("$[recMAIN.Tiefe]");
			int SumUp = HostObject.EvalInt("$[recMAIN.SumUp]");
			int HeaderType = HostObject.EvalInt("$[recMAIN.Header]");
			int FooterType = HostObject.EvalInt("$[recMAIN.Footer]");
			bool FormFeed = HostObject.EvalBool("$[recMAIN.FormFeed]");
			bool LineFeed = HostObject.EvalBool("$[recMAIN.LineFeed]");
			bool LineFeed2 = HostObject.EvalBool("$[recMAIN.LineFeed2]");
			bool Fett = HostObject.EvalBool("$[recMAIN.Fett]");
			bool HideEmpty = HostObject.EvalBool("$[recMAIN.HideEmpty]");
			ChildType Positionen = ChildType.empty; // zeigt an, ob die untergeordneten Positionen sind

			#region Pass 1 Summen bilden
			IReportVariable SummeAlt = HostObject.DefineVariable2("SummeAlt", "N,14,2");
			IReportVariable SummeBil = HostObject.DefineVariable2("SummeBil", "N,14,2");
			IReportVariable SummeNeu = HostObject.DefineVariable2("SummeNeu", "N,14,2");
			string bsPosNr = CalcPosNr(bsParentPosNr);
			string bsPosNr2 = String.IsNullOrEmpty(bsPosNr) ? bsParentPosNr : bsPosNr;
			HostObject.DefineVariable2("mText", "c,80,0");
			HostObject.Set("mText", "$[recMAIN.Text]", true);

			m_recMain.GoNext();
			while ((!m_recMain.Eof) && HostObject.CastInt(m_recMain.Get("Tiefe")) > nTiefe)
			{
				switch (HostObject.EvalInt("$[recMAIN.PosTyp]"))
                {
					case 1:
						Positionen = ChildType.summnodes;
						break;
					case 2:
						Positionen = ChildType.positions;
						break;
				}
				if (HandleRecMain(true, bsPosNr2))
				{
					bResult = true;
				}
			}
			#endregion

			#region Pass 2 Ausgabe
			if (!bSilent)
			{
				bool WithChilds = bResult || (m_AllePositionen && (Positionen != ChildType.empty));

				if (WithChilds)
				{
					if ((Positionen != ChildType.positions) || (!m_NurSummen))
					{
						// restore position before repeat the loop
						m_recMain.Find(nLfdNr.ToString().PadLeft(8));
						PrintSumme_NotEmpty(nTiefe, bsPosNr, bsPosNr2, HeaderType, FooterType, Fett, FormFeed, LineFeed, LineFeed2);
					}
					else
                    {
						PrintSumme_Flat(nTiefe, bsPosNr, HeaderType, FooterType, Fett, FormFeed, LineFeed, LineFeed2);
					}
				}
				else if ((!HideEmpty) || m_AllePositionen)
				{
					PrintSumme_Empty(nTiefe, bsPosNr, HeaderType, FooterType, Fett, FormFeed, LineFeed, LineFeed2);
				}
			}
			#endregion

			HostObject.VariablesPop();

			switch (SumUp)
            {
				case 0:
					AddSummen(SummeAlt.GetDouble(), SummeBil.GetDouble(), SummeNeu.GetDouble());
					break;
				case 1:
					AddSummen(0.00 - SummeAlt.GetDouble(), 0.00 - SummeBil.GetDouble(), 0.00 - SummeNeu.GetDouble());
					break;
			}
			return bResult || (!HideEmpty);
		}

		void PrintSumme_NotEmpty(int nTiefe, string bsPosNr, string bsPosNr2, int HeaderType, int FooterType, bool Fett, bool FormFeed, bool LineFeed, bool LineFeed2)
        {
			// Kopf ausgeben
			if (FormFeed)
			{
				HostObject.FormFeed();
			}
			else if (LineFeed)
			{
				HostObject.LineFeed(1);
			}
			if (HeaderType < 3)
			{
				SetupDetailFont(Fett);
				HostObject.CheckPageSpace(3);
				HostObject.ProcessResource("Header" + HeaderType.ToString()); // + HeaderType.ToString());
			}

			// Details ausgeben mit unschaedlichen Variablen
			HostObject.VariablesPush();
			HostObject.DefineVariable2("SummeAlt", "N,14,2");
			HostObject.DefineVariable2("SummeBil", "N,14,2");
			HostObject.DefineVariable2("SummeNeu", "N,14,2");
			m_recMain.GoNext();
			while ((!m_recMain.Eof) && HostObject.CastInt(m_recMain.Get("Tiefe")) > nTiefe)
			{
				HandleRecMain(false, bsPosNr2);
			}
			HostObject.VariablesPop();

			// Fuss ausgeben
			if (LineFeed2)
			{
				HostObject.LineFeed(1);
			}
			if (FooterType < 3)
			{
				SetupDetailFont(Fett);
				HostObject.CheckPageSpace(1);
				HostObject.ProcessResource("Footer" + FooterType.ToString());
			}
		}

		void PrintSumme_Empty(int nTiefe, string bsPosNr, int HeaderType, int FooterType, bool Fett, bool FormFeed, bool LineFeed, bool LineFeed2)
        {
			if ((HeaderType == 2) || (FooterType < 3))
			{
				if (FormFeed || LineFeed || LineFeed2)
				{
					HostObject.LineFeed(1);
				}
				SetupDetailFont(Fett);
				HostObject.CheckPageSpace(1);
				HostObject.ProcessResource("HeaderOrFooterEmpty");
			}
		}

		void PrintSumme_Flat(int nTiefe, string bsPosNr, int HeaderType, int FooterType, bool Fett, bool FormFeed, bool LineFeed, bool LineFeed2)
		{
			if ((HeaderType == 2) || (FooterType < 3))
			{
				if (FormFeed || LineFeed || LineFeed2)
				{
					HostObject.LineFeed(1);
				}
				SetupDetailFont(Fett);
				HostObject.CheckPageSpace(1);
				HostObject.ProcessResource("HeaderOrFooterFlat");
			}
		}

		bool HandlePosition(bool bSilent, string bsParentPosNr)
		{
			HostObject.VariablesPush();
			m_recBila.Find(HostObject.CastInt(m_recMain.Get("LfdNr")).ToString().PadLeft(8));

			bool bResult = HostObject.EvalBool("$[recBILA.SaldoAlt] <> 0")
				|| HostObject.EvalBool("$[recBILA.SaldoBil] <> 0")
				|| HostObject.EvalBool("$[recBILA.SaldoNeu] <> 0");

			if ((!bSilent) && (bResult || m_AllePositionen) && (! m_NurSummen))
            {
				CalcPosNr(bsParentPosNr);
				SetupDetailFont();
				HostObject.CheckPageSpace(1);
				HostObject.ProcessResource("Account");
			}

			AddSummen(HostObject.EvalDouble("$[recBILA.SaldoAlt]"), HostObject.EvalDouble("$[recBILA.SaldoBil]"), HostObject.EvalDouble("$[recBILA.SaldoNeu]"));
			HostObject.VariablesPop();
			m_recMain.GoNext();
			return bResult;
		}

		bool HandleText(bool bSilent, string bsParentPosNr)
        {
			HostObject.VariablesPush();
			if (!bSilent)
            {
				CalcPosNr(bsParentPosNr);
				SetupDetailFont();
				HostObject.CheckPageSpace(1);
				HostObject.ProcessResource("Remark");
			}
			HostObject.VariablesPop();
			m_recMain.GoNext();
			return false;
        }

		void Tabulieren()
		{
			HostObject.VariablesPush();
			HostObject.DefineVariable2("mFillStart", "d,8,2");
			for (int nCurrent = HostObject.EvalInt("$[Zeile]"); nCurrent < m_ZeileMax; nCurrent += 2)
			{
				HostObject.Set("mFillStart", @" $[RandY] + ($[cyZeile] * " + nCurrent.ToString() + ")", true);
				HostObject.WriteLine(HostObject.EvalString(@"RGBFILL $[RandX];$[mFillStart];$[SizeX];$[cyZeile];15263976"));
			}
			HostObject.VariablesPop();
		}

		string CalcFilterText()
		{
			// Auswertung oder Teilauswertung 
			string bsResult = m_LfdNr != 0 ? "Teilauswertung" : "Auswertung";
			bsResult += " Nr. " + m_LstNr;

			// Zeitraum hinzufuegen
			string tmp1 = HostObject.EvalString("$[recAnfang.OptDataC<6]");
			string tmp2 = HostObject.EvalString("$[recEnde.OptDataC<6]");
			bsResult += " Zeitraum " + tmp1.Substring(4, 2) + "/" + tmp1.Substring(0, 4);
			if (tmp1 != tmp2)
			{
				bsResult += " bis " + tmp2.Substring(4, 2) + "/" + tmp2.Substring(0, 4);
			}
			return bsResult;
		}

		string CalcPosNr(string bsParentPosNr)
		{
			string bsPosNr = m_recMain.Get("PosNr").ToString();

			if (m_recMain.Get("PosTyp").ToString() == "2")
			{
				if (String.IsNullOrEmpty(bsPosNr))
                {
					bsPosNr = m_recMain.Get("KtoVon").ToString();
				}
			}
			else
			{
				if ((!String.IsNullOrEmpty(bsPosNr)) && (!String.IsNullOrEmpty(bsParentPosNr)))
				{
					if ((bsPosNr.Length == 1) && (bsPosNr[0] >= 'a') && (bsPosNr[0] <= 'z'))
						bsPosNr = bsParentPosNr + bsPosNr;
					else
						bsPosNr = bsParentPosNr + "." + bsPosNr;
				}
			}

			HostObject.DefineVariable2("mPosNr", "c,30,0");
			HostObject.Set("mPosNr", bsPosNr, false);
			return bsPosNr;
		}

		void SetupDetailFont(bool bFett)
        {
			if (bFett)
				HostObject.Set("mFontDetail", "$[mFontBold]", true);
			else
				HostObject.Set("mFontDetail", "$[mFontDefault]", true);
		}

		void SetupDetailFont()
		{
			SetupDetailFont(HostObject.EvalBool("$[recMAIN.Fett]"));
		}

		void AddValueTo(string bsVarName, double dValue)
		{
			if (Math.Round(dValue, 2) != 0.00 && HostObject.IsVar(bsVarName))
			{
				IReportVariable v = HostObject.GetVariable(bsVarName);
				v.Set((v.GetDouble() + dValue).ToString("F2"));
			}
		}

		void AddSummen(double dAlt, double dBil, double dNeu)
		{
			AddValueTo("SummeAlt", dAlt);
			AddValueTo("SummeBil", dBil);
			AddValueTo("SummeNeu", dNeu);
		}

		#endregion
	}
}
