/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package csa.tiletools.map;

import csa.gui.dialogs.ShowInfoDialog;
import csa.tiletools.sprites.Sprite;
import csa.tiletools.sprites.SpriteDataPool;
import csa.tiletools.tiles.CompositeTile;
import csa.tiletools.tiles.Tile;
import csa.tiletools.tiles.TileData;
import csa.tiletools.tiles.TileDataPool;
import java.io.File;
import java.util.*;

/**
 *
 * @author salchr
 */
public class TMap
{
    MapPanel mDisplayPanel = null;
    private MapData mData = new MapData();
    ArrayList<Layer> mLayers = new ArrayList<Layer>();

    //private Layer currentLayer = null;
    private int currentLayerNo = -1;
    private LayerDataPool mLayerDataPool = null;

    public ArrayList<Layer> getCurrentLayers()
    {
        return mLayers;
    }
    public LayerDataPool getLayerPool()
    {
        return mLayerDataPool;
    }

    public void updateMapLayerData()
    {
        mData.mLayerData = new Vector<String>();
        for (int i=0; i<mLayers.size(); i++)
        {
            mData.mLayerData.addElement(mLayers.get(i).getData().mName);
        }
    }

    public Layer getCurrentLayer()
    {
        if (currentLayerNo==-1) return null;
        if (currentLayerNo<mLayers.size())
            return mLayers.get(currentLayerNo);
        return null;
    }
    public int getCurrentLayerNo()
    {
        return currentLayerNo;
    }
    public void setCurrentLayerNo(int l)
    {
        currentLayerNo = l;
    }


    public TMap()
    {
        mLayerDataPool = new LayerDataPool("Maps"+File.separator+ "LayerData.xml");
        addLayer(0);
    }
    
    // for composite tiles
    public TMap(Layer l)
    {
        //mLayerDataPool = new LayerDataPool("Maps"+File.separator+ "LayerData.xml");
        addLayer(l);
    }

    public void reInitLayerPool()
    {
        String layerPoolName = "Maps"+File.separator+mData.mName+"LayerData"+".xml";
        
	mLayerDataPool.setFilename(layerPoolName);
    }

    public TMap(MapData data)
    {
        mData = data;
        String layerPoolName = "Maps"+File.separator+data.mName+"LayerData"+".xml";
        mLayerDataPool = new LayerDataPool(layerPoolName);

        Collection<LayerData> colC = mLayerDataPool.getHashMap().values();
        Iterator<LayerData> iterC = colC.iterator();

        while (iterC.hasNext())
        {
            LayerData item = iterC.next();
            Layer layer = new Layer(item);
            layer.isInMap=true;
            mLayers.add(layer);
        }
       Collections.sort(mLayers, new Comparator<Layer>() {@Override
            public int compare(Layer s1, Layer s2) { return s1.getData().mLayerNumber - s2.getData().mLayerNumber; } });
    }

    public MapData getData()
    {
        return mData;
    }

    public void addLayer(Layer layer)
    {
        layer.getData().mLayerNumber = mLayers.size();
        if (layer.getData().mLayerName.length()==0)
            layer.getData().mLayerName = ""+ mLayers.size();
        if (layer.getData().mName.length()==0)
            layer.getData().mName = ""+ mLayers.size();
        
        layer.isInMap=true;
        mLayers.add(layer);

        for (int i=layer.getData().mLayerNumber+1; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            l.getData().mLayerNumber++;
        }
        currentLayerNo =  mLayers.size()-1;
    }

    public String checkName(String name)
    {
        boolean again=false;
        do
        {
            again=false;
            for (int i=0; i< mLayers.size(); i++)
            {
                Layer l = mLayers.get(i);
                String n = l.getData().mName;
                if (n.equals(name))
                {
                    again = true;
                    name+="_1";
                    break;
                }
            }
        }
        while (again);
        return name;
    }
    public void addLayer(Layer newLayer, int pos)
    {

        String name = ""+ pos;
        if (newLayer.getData().mLayerName.length() != 0)
        {
            name = newLayer.getData().mLayerName;
        }
        if (newLayer.getData().mName.length() != 0)
        {
            name = newLayer.getData().mName;
        }
        name = checkName(name);

        newLayer.setLayerNumber(pos);
        newLayer.getData().mLayerName = name;
        newLayer.getData().mName = name;
        newLayer.getData().mLayerNumber = pos;
        newLayer.getData().misVisible=true;

        newLayer.isInMap=true;

        mLayers.add(pos, newLayer);
        mData.mLayerData.add(pos, newLayer.getData().mName);

        for (int i=pos+1; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            l.getData().mLayerNumber++;
        }
    }

    public void addLayer(int pos)
    {
        LayerData newLayerData = new LayerData();
        newLayerData.mLayerNumber = pos;
        newLayerData.mLayerName = ""+ pos;
        newLayerData.mName = ""+ pos;
        newLayerData.misVisible=true;

        Layer newLayer = new Layer(newLayerData);

        mLayers.add(pos, newLayer);
        mData.mLayerData.add(pos, newLayerData.mName);
        currentLayerNo = pos;

        for (int i=pos+1; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            l.getData().mLayerNumber++;
        }
    }

    public void removeLayer(int pos)
    {
        Layer layer = mLayers.get(pos);

        mLayerDataPool.remove(layer.getData());
        // mLayerDataPool.save();
        mData.mLayerData.remove(pos);
        mLayers.remove(pos);

        for (int i=pos; i< mLayers.size();i++)
        {
            mLayers.get(i).getData().mLayerNumber--;
        }
        if (currentLayerNo>=pos) currentLayerNo--;
    }


    public Layer getLayer(int pos)
    {
        if (pos < mLayers.size())
            return mLayers.get(pos);
        return null;
    }
    public void deinit()
    {
        mDisplayPanel = null;
        for (int i=0; i< mLayers.size(); i++)
        {
            mLayers.get(i).deinit();
        }
    }
    public void setDisplay(MapPanel panel)
    {
        mDisplayPanel = panel;
        for (int i=0; i< mLayers.size(); i++)
        {
            mLayers.get(i).setDisplay(panel);
        }
    }
    public Sprite addSprite(Sprite s)
    {
        return getCurrentLayer().addSprite(s);
    }

    // coordinates are in map coordinates, and not scaled!
    // offset is not included in coordinates!
    public Tile addTile(TileData t, int x, int y, boolean inMapCoordinates, TileDataPool tileDataPool, boolean replace)
    {
        return getCurrentLayer().addTile(t, x, y, inMapCoordinates, tileDataPool, true, replace);
    }
    public void addTile(CompositeTile t, int x, int y, boolean inMapCoordinates)
    {
        getCurrentLayer().addTile(t, x, y, inMapCoordinates);
    }

    public void offsetXInc(int inc, boolean allLayers)
    {
        if (allLayers)
        {
            for (int i=0; i< mLayers.size(); i++)
            {
                mLayers.get(i).getData().moffsetX += inc;
            }
        }
        else
        {
            getCurrentLayer().getData().moffsetX += inc;
        }
    }

    public void offsetYInc(int inc, boolean allLayers)
    {
        if (allLayers)
        {
            for (int i=0; i< mLayers.size(); i++)
            {
                mLayers.get(i).getData().moffsetY += inc;
            }
        }
        else
        {
            getCurrentLayer().getData().moffsetY += inc;
        }
    }

    public int getOffsetX(boolean allLayers)
    {
        return getCurrentLayer().getData().moffsetX;
    }
    public int getOffsetY(boolean allLayers)
    {
        return getCurrentLayer().getData().moffsetY;
    }
    public void setOffsetY(int o, boolean allLayers)
    {
        if (allLayers)
        {
            for (int i=0; i< mLayers.size(); i++)
            {
                mLayers.get(i).getData().moffsetY = o;
            }
        }
        else
        {
            getCurrentLayer().getData().moffsetY = o;
        }
    }
    public void setOffsetX(int o, boolean allLayers)
    {
        if (allLayers)
        {
            for (int i=0; i< mLayers.size(); i++)
            {
                mLayers.get(i).getData().moffsetX = o;
            }
        }
        else
        {
            getCurrentLayer().getData().moffsetX = o;
        }
    }
    public void joinLayers(int[] rowConvert)
    {
        int first = -1;
        Layer newLayer = new Layer();
        java.util.Arrays.sort( rowConvert );  
        for (int i=0; i< rowConvert.length; i++)
        {
            int row = rowConvert[i];
         
            if (row == -1) continue;
            if (first == -1) first = row;
            newLayer.moveTiles(mLayers.get(row));
            newLayer.moveSprites(mLayers.get(row));
        }

        if (first == -1) return;
        for (int i=rowConvert.length-1; i>=0 ; i--)
        {
            int row = rowConvert[i];
            removeLayer(row);
        }
        newLayer.orderTiles();
        newLayer.getData().mName = "JoinedLayer_"+first;
        addLayer(newLayer, first);
        currentLayerNo = first;
    }
    
    // position and tile width is both respected
    public int getMapWidth()
    {
        int maxXPos = Integer.MIN_VALUE;
        int minXPos = Integer.MAX_VALUE;
        
        for (int i=0; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            if (maxXPos<l.getMaxX()) maxXPos = l.getMaxX();
            if (minXPos>l.getMinX()) minXPos = l.getMinX();
        }
        return maxXPos - minXPos;
    }
    public int getMapHeight()
    {
        int maxYPos = Integer.MIN_VALUE;
        int minYPos = Integer.MAX_VALUE;
        
        for (int i=0; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            if (maxYPos<l.getMaxY()) maxYPos = l.getMaxY();
            if (minYPos>l.getMinY()) minYPos = l.getMinY();
        }
        return maxYPos - minYPos;
    }

    public int getMinTileWidth()
    {
        int minWidth = Integer.MAX_VALUE;
        
        for (int i=0; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            if (minWidth> l.getMinTileWidth()) minWidth = l.getMinTileWidth();
        }
        return minWidth;
    }
    public int getMinTileHeight()
    {
        int minHeight = Integer.MAX_VALUE;
        
        for (int i=0; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            if (minHeight> l.getMinTileHeight()) minHeight = l.getMinTileHeight();
        }
        return minHeight;
    }
    public int getMinX()
    {
        int minXPos = Integer.MAX_VALUE;
        for (int i=0; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            if (minXPos>l.getMinX()) minXPos = l.getMinX();
        }
        return minXPos;
    }
    public int getMinY()
    {
        int minYPos = Integer.MAX_VALUE;
        for (int i=0; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            if (minYPos>l.getMinY()) minYPos = l.getMinY();
        }
        return minYPos;
    }
    public int getTileCount()
    {
        int count = 0;
        
        for (int i=0; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            count += l.getTileCount();
        }
        return count;
    }
    
    // takes the lowest found coordinate in the map
    // and zeroes it (and all other tiles)
    public void toZero()
    {
        int minX = getMinX();
        int minY = getMinY();
        for (int i=0; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            l.toZero(minX, minY);
        }
        
    }
    public void toISOZero()
    {
        int minX = getMinX();
        int minY = getMinY();
        
        Layer ll = getCurrentLayer();
        
        if (ll.mTiles.size()<=0)
        {
            toZero();
            return;
        }
        Tile t = ll.mTiles.get(0);
        if (t.getData().getType() != 1)
        {
            toZero();
            return;
        }
        int width = t.getMaxWidthUnscaled();
        int height = t.getMaxHeightUnscaled();
        
        
        for (int i=0; i< mLayers.size(); i++)
        {
            Layer l = mLayers.get(i);
            /// bal l.toZero(minX, minY, width/2, height/2);
        }
        
    }
    public Layer buildFogLayer(TileData fogTile)
    {
        int widthInPixel = getMapWidth();
        int heightInPixel = getMapHeight();

        int mainLayerNo =0;
        
        // assuming layer No 1 as main reference layer (0 assumed to be background)
        if (mLayers.size()>1)mainLayerNo = 1;

        Layer mainLayer = getLayer(mainLayerNo);
            
        Layer newLayer = new Layer();
        
        
        LayerData newData = newLayer.getData();
        LayerData mainData = mainLayer.getData();
        
        
        newData.mISOBlockWrap = mainData.mISOBlockWrap;
        newData.mWrapHorizontal = mainData.mWrapHorizontal;
        newData.mWrapVertical = mainData.mWrapVertical;
        newData.misVisible = true;
        newData.mpurposeTyp = "FOG";
        
        
        if (mainData.mWrapHorizontal)
        {
            int div = widthInPixel%fogTile.getWidth();
            if (div != 0) 
            {
                ShowInfoDialog.showInfoDialog("Wrapping with fogtile does not fit (h)!");
                return null;
            }
        }
        if (mainData.mWrapVertical)
        {
            int div = heightInPixel%fogTile.getHeight();
            if (div != 0) 
            {
                ShowInfoDialog.showInfoDialog("Wrapping with fogtile does not fit (v)!");
                return null;
            }
        }
        addLayer(newLayer);
        newLayer.setDisplay(mDisplayPanel);

        for (int y = getMinY(); y <getMinY()+heightInPixel; y+=fogTile.getHeight())
        {
            for (int x = getMinX(); x <getMinX()+widthInPixel; x+=fogTile.getWidth())
            {
                newLayer.addTile(fogTile, x, y, true);
            }
        }
        
        // get needed dimensions
        // calc width hight in tiles
        // add Fog tiles
        // add wrapping etc to layer
        //
        newData.mName = "FogOfWar";
        newData.mLayerName = "FogOfWar";
        newLayer.makeRegular();
        
        
        newData.mFogFileName = fogTile.getTileSetFileName();
        newData.mFogName = fogTile.getName();


        mDisplayPanel.setMapChanged(true, true);
        mDisplayPanel.updateNeeded(true);
        
        
        
        return newLayer;
    }
    
}
