/** klasa reprezentuje girda inventory - jeden z gridow na przedmioty
 *	gracz ma kilka takich gridow : plecak glowny, pas na naboj itp.
 */

public class InvGrid implements ISaveGame
{

//////////////////////////////////
// atrybuty
//////////////////////////////////
	
	/** rozmiar grida  - ilosc kratek inventory grid
	 */
	int nCellsAmountX = 0;
	int nCellsAmountY = 0;
	
	/** wspolrzedne tekstury grida
	 */
	int nGridPosX = 0;
	int nGridPosY = 0;
	
	/** tablica ze wspolrzednymi kratek grida
	 */
	Vector aCellPoints[][] = null;
	
	/** tablica wolnych kratek w gridzie
	 */
	boolean aFreeCells[][] = null;

	
/////////////////////////////////
// metody
/////////////////////////////////
	
//------------------------------------------------------------------------
	/** metoda inicjalizujaca odpowiednie parametry grida na podstawie jego typu
	 */
	public void InitializeGrid(int grid_type, UIWindow cInvWindow)
	{
        Vector vPos = null;
		switch (grid_type) 
		{
		case Inventory._SLOT_01: 
            vPos = GetSlotPos(Inventory._SLOT_01, cInvWindow);
			nGridPosY = (int)vPos.fY;
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_01;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_01;
			nGridPosX = (int)vPos.fX;
			break;
			
		case Inventory._SLOT_02: 
            vPos = GetSlotPos(Inventory._SLOT_02, cInvWindow);
			nGridPosY = (int)vPos.fY;
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_02;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_02;
			nGridPosX = (int)vPos.fX;
			break;
			
		case Inventory._SLOT_03: 
            vPos = GetSlotPos(Inventory._SLOT_03, cInvWindow);
			nGridPosY = (int)vPos.fY;
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_03;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_03;
			nGridPosX = (int)vPos.fX;
			break;
			
		case Inventory._SLOT_04: 
            vPos = GetSlotPos(Inventory._SLOT_04, cInvWindow);
			nGridPosY = (int)vPos.fY;
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_04;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_04;
			nGridPosX = (int)vPos.fX;
			break;
			
		case Inventory._SLOT_05: 
            vPos = GetSlotPos(Inventory._SLOT_05, cInvWindow);
			nGridPosY = (int)vPos.fY;
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_05;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_05;
			nGridPosX = (int)vPos.fX;
			break;
			
		case Inventory._SLOT_06: 
            vPos = GetSlotPos(Inventory._SLOT_06, cInvWindow);
			nGridPosY = (int)vPos.fY;
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_06;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_06;
			nGridPosX = (int)vPos.fX;
			break;
			
		case Inventory._SLOT_07: 
            vPos = GetSlotPos(Inventory._SLOT_07, cInvWindow);
			nGridPosY = (int)vPos.fY;
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_07;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_07;
			nGridPosX = (int)vPos.fX;
			break;
		
        case Inventory._SLOT_MISSION: 
            vPos = GetSlotPos(Inventory._SLOT_MISSION, cInvWindow);
			nGridPosY = (int)vPos.fY;
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_MISSION;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_MISSION;
			nGridPosX = (int)vPos.fX;
			break;
			
			
			
		case Inventory._AI_GRID: //AI Inventory
			//Log("[InvGrid.InitializeGrid] Initalizing AI GRID");
            vPos = GetSlotPos(Inventory._AI_GRID, cInvWindow);
			nGridPosY = (int)vPos.fY;
			nCellsAmountX = EHudInvParams._CELLS_X_AI;
			nCellsAmountY = EHudInvParams._CELLS_Y_AI;
			nGridPosX = (int)vPos.fX;
			break;	
            
		}//switch
        
        ComputeCellPoints();
	}
    
    public void InitializeGrid(int grid_type)
	{
		switch (grid_type) 
		{
		case Inventory._SLOT_01: 
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_01;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_01;
			break;
			
		case Inventory._SLOT_02: 
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_02;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_02;
			break;
			
		case Inventory._SLOT_03: 
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_03;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_03;
			break;
			
		case Inventory._SLOT_04: 
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_04;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_04;
			break;
			
		case Inventory._SLOT_05: 
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_05;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_05;
			break;
			
		case Inventory._SLOT_06: 
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_06;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_06;
			break;
			
		case Inventory._SLOT_07: 
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_07;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_07;
			break;
		
        case Inventory._SLOT_MISSION: 
			nCellsAmountX = EHudInvParams._CELLS_X_SLOT_MISSION;
			nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_MISSION;
			break;
			
			
			
		case Inventory._AI_GRID: //AI Inventory
			//Log("[InvGrid.InitializeGrid] Initalizing AI GRID");
    		nCellsAmountX = EHudInvParams._CELLS_X_AI;
			nCellsAmountY = EHudInvParams._CELLS_Y_AI;
			break;	
            
		}//switch
				
		//inicjalizuje tablice cellpointsow
        aCellPoints = new Vector[nCellsAmountY][nCellsAmountX];
		ComputeCellPoints();
		
		//inicjalizuje tablice wolnych miejsc w plecaku
		aFreeCells = new  boolean[nCellsAmountY][nCellsAmountX];
        ClearGrid();
		
		// Log("[InvGrid.InitializeGrid] OK\n");
	}
    
	Vector GetSlotPos(int nSlot, UIWindow cInvWindow)
    {
        switch (nSlot) 
		{
		case Inventory._SLOT_01: 
            return cInvWindow.GetElem("ID_SLOT_01").GetElem("ID_GRID").GetPos();
		case Inventory._SLOT_02:
            return cInvWindow.GetElem("ID_SLOT_02").GetElem("ID_GRID").GetPos();
		case Inventory._SLOT_03: 
            return cInvWindow.GetElem("ID_SLOT_03").GetElem("ID_GRID").GetPos();
		case Inventory._SLOT_04: 
            return cInvWindow.GetElem("ID_SLOT_04").GetElem("ID_GRID").GetPos();
		case Inventory._SLOT_05: 
            return cInvWindow.GetElem("ID_SLOT_05").GetElem("ID_GRID").GetPos();
		case Inventory._SLOT_06: 
            return cInvWindow.GetElem("ID_SLOT_06").GetElem("ID_GRID").GetPos();
		case Inventory._SLOT_07: 
            return cInvWindow.GetElem("ID_SLOT_07").GetElem("ID_GRID").GetPos();
		case Inventory._SLOT_MISSION: 
            return cInvWindow.GetElem("ID_SLOT_MISSION").GetElem("ID_GRID").GetPos();
        case Inventory._AI_GRID: 
            return cInvWindow.GetElem("ID_SLOT_AI").GetElem("ID_GRID").GetPos();
		}//switch
        return null;
    }
//------------------------------------------------------------------------
	/** Metoda aktywujaca InvGrid
	 */
	public void Activate()
	{
    }
	
//------------------------------------------------------------------------
	/** metoda deaktywujaca InvGrid
	 */
	public void Deactivate()
	{
	}
	
//------------------------------------------------------------------------
	/** Metoda wypelnia tablice cell pointsow wpolrzednymi ekranowymi 
	  *	lewych, gornych rogow kazdej z cel grida 
	  */
	 public void ComputeCellPoints()
	 {
        if(aCellPoints != null)
        {
            Vector base = new Vector(nGridPosX, nGridPosY,0);	 
		    for (int row = 0; row<nCellsAmountY; row++)
			    for (int col = 0; col<nCellsAmountX; col++)
				    aCellPoints[row][col] = new Vector(base.fX+col*EHudInvParams.GetCellWidth(),
                                                       base.fY+row*EHudInvParams.GetCellHeight(),
                                                       0);
        }
	 }
     
//-------------------------------------------------------------------------------     
     /** metoda czysci cele grida - ustwia jako wolne
      */
     public void ClearGrid()
     {
        if(aFreeCells != null)
        {
            for (int i=0; i<nCellsAmountY; i++)
			    for (int j=0; j<nCellsAmountX; j++)
				    aFreeCells[i][j] = true;
        }
     }
    
//-------------------------------------------------------------
     
	/** metoda sprawdza czy dany przedmiotu znajduje sie w calosci
	 *  poza gridem
	 */
	public boolean IsOutOfGrid(InvObject InvObj)
	{
		boolean ret = true;
		boolean x = true;
		boolean y = true;
        
        // brak obiektu
        if(InvObj == null) 
            return true;
        
        // polozenie obiektu reprezentuje sprite.
        // brak spirita => nic nie wiemy o polozeniu
        if(InvObj.cInvObjSprite == null)
            return true;
        
        float nPosSpriteX = InvObj.cInvObjSprite.cActualSpritePos.fX;
        float nPosSpriteY = InvObj.cInvObjSprite.cActualSpritePos.fY;

        
		if ((nPosSpriteX + InvObj.nCellsWidth*EHudInvParams.GetCellWidth() < aCellPoints[0][0].fX ) ||
			(nPosSpriteX > aCellPoints[nCellsAmountY-1][nCellsAmountX-1].fX + EHudInvParams.GetCellWidth()))
			x = true;
		else
            x = false;
        
		if ((nPosSpriteY + InvObj.nCellsHeight*EHudInvParams.GetCellHeight() < aCellPoints[0][0].fY) ||
			(nPosSpriteY > aCellPoints[nCellsAmountY-1][nCellsAmountX-1].fY + EHudInvParams.GetCellHeight()))
			y = true;
		else 
            y = false;

		if (x || y)
            return true;
		else
            return false;
	}
    
//-------------------------------------------------------------------------
	/**metoda zwraca wolne miejsce w plecaku do ktorego mozna dodac przedmiot
	 * szuka na podstawie podanych rozmiarow przedmiotu
	 * jesli zwraca Vect (-1,0,0) to nie ma miejsca w plecaku
	 * @param sizeX
	 * @param sizeY
	 */
	public Vector FindFreeCell(int sizeX, int sizeY)	
	{
		boolean free = false;
		
		Vector retVect = new Vector(-1,0,0);
		
		for (int y = 0; y <= nCellsAmountY - sizeY; y++)
		{
			for (int x=0; x<=nCellsAmountX-sizeX; x++)
			{
				free = IsSpaceInPlace(y, y+sizeY-1, x, x+sizeX-1);
				if (free) 
				{
					retVect = new Vector(x,y,0);
					return retVect;
				}//if 
				
			}//for x
			
		}//for y
		
		return retVect;
	}
//-------------------------------------------------------------------
	/** metoda pomocnicza do szukania miejsca w plecaku
	 */
	public boolean IsSpaceInPlace(int y_p, int y_k, int x_p, int x_k)
	{
		for (int yy = y_p; yy <= y_k; yy++)
		{
			for (int xx = x_p; xx <= x_k; xx++)
			{
				if (aFreeCells[yy][xx] == false) 
                    return false;
			}//for xx
			
		}//for yy
		
		return true;
	}
//------------------------------------------------------------------	     
    /** metoda sprawdza czy w gridzie zmiesci sie podany obiekt
      */
     public boolean IsSpaceForInvObj(InvObject inv_obj)
     {
        int sizeX = inv_obj.nCellsWidth;
	    int sizeY = inv_obj.nCellsHeight;
         
        boolean free = false;
			
		for (int y=0; y<=nCellsAmountY-sizeY; y++)
		{
			for (int x=0; x<=nCellsAmountX-sizeX; x++)
			{
				free = IsSpaceInPlace(y, y+sizeY-1, x, x+sizeX-1);
				if (free) 
				{
					return true;
				}//if 
				
			}//for x
			
		}//for y
		
		return false;   
     }

//-------------------------------------------------------------------
	/** meotda ustawia podane cellsy w plecaku jako zajete
	 */
	public void SetTakenCells(int y, int sizeY, int x, int sizeX)
	{
		for (int yy = y; yy <= y + sizeY - 1; yy++)	
			for (int xx = x; xx <= x + sizeX - 1; xx++)
				aFreeCells[yy][xx] = false;
	}
//-------------------------------------------------------------------
	/** metoda ustawia podane cellsy w plecaku jako wolne
	 */
	public void SetFreeCells(int y, int sizeY, int x, int sizeX)
	{
		for (int yy = y; yy <= y + sizeY - 1; yy++)	
			for (int xx = x; xx <= x + sizeX - 1; xx++)
				aFreeCells[yy][xx] = true;
	}
    
    boolean AreCellsFree(int y, int sizeY, int x, int sizeX)
	{
		for (int yy = y; yy<=y+sizeY-1; yy++)	
			for (int xx = x; xx<=x+sizeX-1; xx++)
				if (aFreeCells[yy][xx] == false)
                    return false;
        return true;
	}

//------------------------------------------------------------------	
	 /** metoda znajduje najblizy wolny CellPoint do podanego wektora w pewnym promieniu
	  *  i zwraca jako wektor wspolrzedne celi
	  *  jesli zwraca Vect (-1,0,0) to nie ma miejsca w plecaku
	  */
	 Vector FindNearestCell(Vector pos, InvObject Iobj, float range_max)
	 {
		boolean bIsFree = false;
        
		float range = 0.0f;
		float range_min = range_max; // dalej niz range_max nie szukamy
        
		Vector retVect = new Vector(-1,0,0);
        
		for (int row = 0; row <= nCellsAmountY - Iobj.nCellsHeight ; row++)
			for (int col =0; col <= nCellsAmountX - Iobj.nCellsWidth; col++)
			{
				range = (float)java.lang.Math.sqrt(( aCellPoints[row][col].fX - pos.fX )*( aCellPoints[row][col].fX - pos.fX ) + ( aCellPoints[row][col].fY - pos.fY )*( aCellPoints[row][col].fY - pos.fY ));	
				
				if ( range < range_min )
				{
					range_min = range;
			
					bIsFree = IsSpaceInPlace(row, row + Iobj.nCellsHeight - 1, col, col + Iobj.nCellsWidth - 1);
					if (bIsFree) //jest wolne miejsce
					{
						retVect = new Vector(col,row,range_min);
					}
					else //nie ma wolnego miejsca
					{
						range_min = 10000.0f;
					}
				}//if
			}// for col
		
		//Log("!!! row = "+retVect.fY+" col="+retVect.fX+"\n");
		
		return retVect;
	 }
     
//------------------------------------------------------------------	
     /** metoda ustawia odpowiednie poloznie grida wzgledem pozycji
      *  sprite'a z inventory playera (tekstura plecaka)
      */
     public void UpdateInventoryGridsPos(int grid_type, int rel_pos_x, int rel_pos_y, UIWindow cInvWindow)
     {
         Vector vPos = null;
         vPos = GetSlotPos(grid_type, cInvWindow);
         nGridPosY = rel_pos_y + (int)vPos.fY;
         nGridPosX = rel_pos_x + (int)vPos.fX;
         switch (grid_type) 
         {
         case Inventory._SLOT_01: 
             nCellsAmountX = EHudInvParams._CELLS_X_SLOT_01;
             nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_01;
             break;
             
         case Inventory._SLOT_02: 
             nCellsAmountX = EHudInvParams._CELLS_X_SLOT_02;
             nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_02;
             break;
             
         case Inventory._SLOT_03: 
             nCellsAmountX = EHudInvParams._CELLS_X_SLOT_03;
             nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_03;
             break;
             
         case Inventory._SLOT_04: 
             nCellsAmountX = EHudInvParams._CELLS_X_SLOT_04;
             nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_04;
             break;
             
         case Inventory._SLOT_05: 
             nCellsAmountX = EHudInvParams._CELLS_X_SLOT_05;
             nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_05;
             break;
             
         case Inventory._SLOT_06: 
             nCellsAmountX = EHudInvParams._CELLS_X_SLOT_06;
             nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_06;
             break;
             
         case Inventory._SLOT_07: 
             nCellsAmountX = EHudInvParams._CELLS_X_SLOT_07;
             nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_07;
             break;
             
         case Inventory._SLOT_MISSION: 
             nCellsAmountX = EHudInvParams._CELLS_X_SLOT_MISSION;
             nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_MISSION;
             break;
         case Inventory._AI_GRID: 
             nCellsAmountX = EHudInvParams._CELLS_X_SLOT_MISSION;
             nCellsAmountY = EHudInvParams._CELLS_Y_SLOT_MISSION;
             break;
             
		}//switch
				
        // update wspolrzednych poszczegolnych kratek
		ComputeCellPoints();
     }
//-------------------------------------------------------------------------------        
     /** metoda ustawia domyslne polozenie gridow do trybu inventory 
      * (takie jak w trakcie gry)
      */
     public void SetInventoryGridsInGamePos(int grid_type, UIWindow cInvWindow)
     {
         
         Vector vPos = null;
         vPos = GetSlotPos(grid_type, cInvWindow);
         nGridPosY = (int)vPos.fY;
         nGridPosX = (int)vPos.fX;
        
		// update wspolrzednych poszczegolnych kratek
        ComputeCellPoints();
     }
   
//------------------------------------------------------------------------     
     /** POMOC POMOC POMOC
	 */	 
	public void PrintCellPoints()
	{
		/*
        Log("[InvGrid.PrintCellPoints] Wymiary = "+nCellsAmountY+" "+nCellsAmountX+"\n" );
		
		String tekst = new String("");
		for (int row = 0; row<nCellsAmountY; row++)
		{
			tekst = "";
			for (int col = 0; col<nCellsAmountX; col++)
			{
				tekst+=" "+aCellPoints[row][col].fX+","+aCellPoints[row][col].fY;
			}
			Log(tekst+"\n");
		}//for row
	*/
	}
	
//-------------------------------------------------------------------	
    /** metoda pomocnicza - wyswietla tabele wolnych miejsc w pleacku
	 */
	public void PrintFreeCells()
	{
        String row = new String("");
		
		for (int i=0; i<nCellsAmountY; i++)
		{
			row = "";
			for (int j=0; j<nCellsAmountX; j++)
			{
				if (aFreeCells[i][j]) row+=" 0";
					else row+=" 1";
				
			}// for j
			GameObject.Log (row+"\n");
		}//for i 
	}	
//-------------------------------------------------------------------------------             
	
    //*********************************************************
	//					SaveGame
    //*********************************************************
	
    /** Metoda wczytujaca zapisane dane w Save gracza
     */	
    public void SGLoadChunk(FileChunk cParentFC)
    {	
		FileChunk.Log("[InvGrid.SGLoadChunk]\n");
		
		FileChunk cFC = GameObject.LoadChunk(cParentFC);   
		
        if (cFC.GetID() == ESGChunksChrome._CHK_INV_GRID)
        {	
            int nCellsX = cFC.LoadInt();
            int nCellsY = cFC.LoadInt();
            
            if(nCellsX != nCellsAmountX ||
               nCellsY != nCellsAmountY)
            {
                GameObject.CrashLog("InvGrid read=<"+nCellsAmountX+","+nCellsAmountY+"> expected=<"+nCellsX+","+nCellsY+">\n");
            }

			// tablica wolnych kratek w gridzie
			for (int i=0; i < nCellsY; i++)
				for (int j=0; j < nCellsX; j++)
					aFreeCells[i][j] = cFC.LoadBool();			
        }
		
		cFC.delete();
    }
    
    /** Metoda zapisujaca dane do Save gracza
     */	
    public void SGSaveChunk(FileChunk cFCParent)
    {
		FileChunk.Log("[InvGrid.SGSaveChunk]\n");
		
        FileChunk cFC = GameObject.NewChunk(ESGChunksChrome._CHK_INV_GRID, cFCParent);
		
        cFC.SaveInt(nCellsAmountX);
        cFC.SaveInt(nCellsAmountY);
        
		// tablica wolnych kratek w gridzie
		for (int i=0; i < aFreeCells.length; i++)
			for (int j=0; j < aFreeCells[i].length; j++)
				cFC.SaveBool(aFreeCells[i][j]);

        cFC.delete();
    }	    		
	
	public void SGUpdate() {}
}
