//---------------------------------------------------------------------------
#ifndef AnalyseSkemaH
#define AnalyseSkemaH
#include <iostream.h>
#include <stdlib.h>
#include "Portal.h"
#include "comm.h"
//---------------------------------------------------------------------------
//De makismale grænse på skemaet.
const int max_x = 5;
const int max_y = 8;

class AnalyseSkema
{
public:
  //Konstruktør
    AnalyseSkema(Portal* Port_, string HoldID_, string FagID_,
                 string LaererID_, string LokaleID_,
                 int blok_, int PlanLagteLektioner_,
                 int user_max_x_, int user_max_y_);
  //Copykonstruktør
    AnalyseSkema(const AnalyseSkema& a);

  //press funktioner
    ///Funktionen forsøger at presse alle lektioner på skemaet op ad.
    void PresSkemaOp();

  //frie plads funktioner
    //Funktionen forsøger at skabe frie lektioner ved flytte lektioner der ligger
	//opad enkelte felter med værdien 6. NB funktionen stopper selv når der er
	//skabt det antallet af frie lektioner således at planlagte lektioner kan
	//blive opfyldt. HVis dette sker returneres en sandhedsværdi herfor
    bool SkabFrieDobbeltLektioner();

    //Funktionen forsøger at skabe frie lektioner på kolonner uden 5 felter.
	//Funktionen forsøger at skaber det antal frie lektioner som mangler at
	//blive lagt. Hvis det opnåes skabe det fornødne antal frie lektioner
	//returneres en sandhedsværdi herfor.
    bool SkabFrieLektioner();

  //Lægge funktion
    //Funktionen forsøger at lægge det antal lektioner som mangler at blive lagt
	//i alle felter med værdien 4. Hvis funktionen opnår at lægge alle dem som
	//mangler stopper den og returnere en sandhedsværdi. Det bør nævnes at
	//funktionen kræver at alle felter med 4 forinden er blevet vurderet således
	//at der kun er dem tilbage hvor der kan ligge nogen faglektioner...!!
	//NB: funktionen kan lægge for både dobbelt og enkelt lektioner.
	//LL angiver det antal som lægges under processen.
    bool LaegFagLektioner(int& LL);

  //soege funktion
    //Funktionen lokalisere faglektioner på skemaet i henholdsvis felter med
	//værdien 10 eller 3. HVis et felt er en fag lektion ændres dens værdi til 5.
    void FindFagLektioner();

    //Funktionen alle ikke egnede frie (4) lektioner på skemaet, således at der
	//kun er dem tilbage hvorpå der kan ligge en dobbelt lektion.
	//Funktionen forudsætter at alle frie felter der ligger i kolonner med
	//faglektioner har fået ændret deres værdi til 6.!
    void FjernIkkeEgnedeDobbeltFagLektioner();

    //Funktionen fjerne alle ikke egnede frie felter som ikke kan benyttes til
	//enkelt lektioner. Det forudsættes at alle frie lektioner der ligger i
	//kolonner med fag lektioner har fået ændret deres værdi til 6.
    void FjernIkkeEgnedeEnkeltFagLektioner();

    //Funktionen ændre de frie felter som ligger på kolonner med faglektioner
	//til værdien 6. Det forudsættes at der forinden er søgt efter de faglektioner
	//som måtte eksistere på skemaet.
    void FindFrieFagLektioner();

  //access funktioner
    int AntalAfVaerdi(const int& vaerdi);
    void IndskrivVaerdi(int vaerdi, int x, int y);
    void IndskrivDobbeltVaerdi(int vaerdi, int x, int y);
    int Lagt() { return LagteLektioner - TidligereLagt; }
    int TidligerLagt() { return TidligereLagt; }
    void AendreBlokTil(int vaerdi) { blok = vaerdi; }

  //Opret skema funktioner
    //Funktionen vurdere om et felt er en den første del af en dobbelt lektion i et
	//givent koordinat.
    void LavDobbeltLektionsSkema(AnalyseSkema* a);
    void LavHLPSkema();
    void LavHLPLSkema();

  //Udskrivs funktion
    friend ostream& operator <<(ostream& ud, const AnalyseSkema a);

private:
  //press funktioner
    //Funktionen forsøger at flytte alle felter med værdierne 5 op i den
	//kolonne som de ligger i.
    void Flyt5FelterOp();

    //FUnktionen forsøger at presse en bestemt værdi på analyse skemaet op på hele
	//skemaet. Typen giver udtryk for om der skal byttes med vaerdier forskeligt fra 4,
	//eller med vaerdier lig 4.
    void PresVaerdiOp(int type, int vaerdi);

  //Bytte Funktioner
    //Funktionen forsøger at bytte feltet angivet med koordinatet væk til
	//et felt som den har mulighed for at bytte med beskrevet i bytteværdierne.
	//Funktionen stopper i det øjeblik den har kunne bytte feltet angivet
	//i koordinatet væk. Hvis dette sker returneres en sandhedsværdi.
    bool BytBestemtFelt(int fra_x, int fra_y);

	//Funktionen forsøger at bytte en bestemt værdi fra et givent koordinat med
	//en række bytte tal. FOr hvert enkelt felt på skemaet vurderes om dennes
	//værdi tilhører bytte tallene. Hvis dette er tilfældet forsøges en bytning
	//(antal = antallet af bytte værdier i arrayet "byttetal")
	//Funktionen stopper dersom den har kunnet bytte feltet væk samt
	//returnere herefter en sandhedsværdi.
    bool BytMedUdvalgteFelter(int vaerdi, int fra_x, int fra_y,
                                        int* byttetal, int antal);

    //Funktionen forsøger at bytter en given værdi i et bestemt felt, med
	//hvilken som helst felt med værdien 6. Funktionen stopper dersom den
	//har fundet en som kan byttes samt returnere en sandhedsværdi herfor.
    bool BytMed6Felter(int vaerdi,  int fra_x, int fra_y,
                       int ikke_x = -1, int ikke_y = -1);

  //soege funktion
    //Funktionen finder koordinatet på givne søgte værdi.
	//Man kan sætte det koordinat som søgningen skal starte fra v.h.a
	//det overførte koordinat.
    bool NaesteVaerdi(int vaerdi, int& x, int& y);

  //access funktioner
    void AendreVaerdiICol(int fra_vaerdi, int til_vaerdi, int x, int y = 0);

  //Kontrol funktioner
    //Funktionen vurdere om en given værdi eksistere i en bestemt kolonne.
	//Funktionen returnere en sandhedsværdi herfor samt koordinatet
	//for den søgte værdi.
    bool FindesICol(int vaerdi, int x, int& y);

    //Funktionen vurdere om et felt er en den første del af en dobbelt lektion i et
	//givent koordinat.
    bool ErVaerdiDobbeltLektion(int vaerdi, int x, int y);

    //Funktionen vurdere om lektionerne i 2 givne koordinater kan byttes.
	//Hvis de kan det byttes de.... Bytningen foretages udfra den givne værdi.
	//Hvis bytningen har fundet sted returneres en sandhedsværdi.
    bool KanBytteForVaerdi(int vaerdi, int fra_x, int fra_y,
                                     int til_x, int til_y);

    bool KontrollerKoordinat(const int& x, const int& y);
    bool KontrollerVaerdi(const int& vaerdi);

  //variable
    //Indeholder det skema hvori alle værdierne skal indføres, og hvorpå selve
    //analysen skal foregå.
    int Askema[max_x][max_y];

    //Angiver den af brugeren bestemte maximale x og y værdi.
    int user_max_x, user_max_y;

    //Angiver for hvem skemaet giver udtryk for.
    string HoldID, LaererID, LokaleID, FagID;

    //Angiver den blokstørrelse/lektionstørrelse som lektionerne skal lægges i.
    //den kan kun være henholdsvis 1 og 2.
    int blok;

    //Angiver antallet af lagte og planlagte lektioner..
    int PlanlagteLektioner, LagteLektioner, TidligereLagt;

    //Angiver hvilke værdier som en bestemt værdi kan byttes med på skemaerne.
    //Den første værdi i 2D arrayet giver udtryk for hvilken værdi der er tale om
    //og den nulte værdi i den anden del af arrayet giver udtryk for hvor mange
    //tal som værdien kan byttes med ([2][0])...
    int BytteVaerdier[11][4];

    //Angiver om skemaet er et HLP-(0), HLPL-(1) eller Dobbelt skema(2)..
    int SkemaType;

    //Angiver de tal som på skemaerne er sværest at flytte. Dvs de værdier
    //som derfor bør flyttes først
    int VaerdiGrad[7];

    //Angiver en pointer til det skema som dobbelt skemaet er bygget på..
    //Dvs at denne variabel kun bliver benyttet hvis der er tale om
    //et dobbelt skema, og formålet med den er at kunne ændre på det grundlæggende
    //skema hvis man ændre noget på det dobbelte skema.
    AnalyseSkema* GamleSkema;

    Portal* Port; //pointer til Portalen...
    comm comm;    //communikations objekt.
};

#endif
