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

import csa.Global;
import csa.config.Configuration;
import csa.gui.Windowable;
import csa.gui.components.CSAView;
import csa.gui.dialogs.InternalFrameFileChoser;
import csa.tiletools.graphics.BaseImageData;
import csa.tiletools.graphics.ImageComponent;
import csa.tiletools.graphics.ImageSequence;
import csa.tiletools.graphics.ImageSequenceData;
import csa.tiletools.graphics.ImageSequenceDataPool;
import csa.tiletools.tiles.CompositeTile;
import csa.tiletools.tiles.Tile;
import csa.tiletools.tiles.TileData;
import csa.tiletools.tiles.TileDataPool;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.*;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.AbstractTableModel;

/**
 *
 * @author salchr
 */
public class GrowTilesPanel extends javax.swing.JPanel implements Windowable{

    int inSetting;
    private TileGrowthData mTileGrowthData = new TileGrowthData();
    private TileGrowthDataPool mTileGrowthDataPool;

    class TileCollectionList
    {
        public ArrayList<String> fileNames = new ArrayList<String>();
        public ArrayList<String> classNames = new ArrayList<String>();
    }
    TileCollectionList mCurrentList = new TileCollectionList();
    
    
    HashMap<String, TileData> tileCache = new HashMap<String, TileData>();

    Vector <TileData> mAllTilesInClass = new Vector <TileData>();
    private TileDataPool mTileDataPool = null;
    private int mClassSetting=0;
    private CSAView mParent = null;
    private javax.swing.JMenuItem mParentMenuItem = null;
    int selectedRow = -1;
    //Vector<Integer> vcolors = new Vector<Integer>();
    //HashMap<Integer, TileImageData> colors = new HashMap<Integer, TileImageData>();
    boolean notDragged = true;
    Layer mLayer = null;
    Layer mSourceLayer = null;
    boolean mSuccessfull = false;
    public boolean successfull()
    {
        return mSuccessfull;
    }

    class TileImageData
    {
        TileData tile=null;
        BufferedImage image=null;
    }


    @Override
    public void closing(){}
    @Override
    public void setParentWindow(CSAView jpv)
    {
        mParent = jpv;
    }
    @Override
    public void setMenuItem(javax.swing.JMenuItem item)
    {
        mParentMenuItem = item;
        mParentMenuItem.setText("Grow tiles");
    }
    @Override
    public javax.swing.JMenuItem getMenuItem()
    {
        return mParentMenuItem;
    }
    @Override
    public javax.swing.JPanel getPanel()
    {
        return this;
    }

    /**
     * Creates new form ColorReduceJPanel
     */
    public GrowTilesPanel() {
        initComponents();
        jTable1.setModel(getTableModel());
        resetConfigPool(false, "");
    }
    MapEdit mMPParent = null;
    public GrowTilesPanel(Layer l, MapEdit p, Layer sLayer) {
        initComponents();
        
        mSourceLayer = sLayer;
        setSources(true);
        mLayer = l;
        mMPParent = p;
        jTable1.setModel(getTableModel());
        mTileGrowthDataPool = new TileGrowthDataPool();
        resetConfigPool(false, "");
    }
    private HashMap<String, Tile> getSources()
    {
        // todo, should parse textfield
        // this is just a quick workaround top get going!
        return setSources(false);
    }
    private HashMap<String, Tile> setSources(boolean updateUI)
    {
        String sourcesString ="";
        HashMap<String, Tile> sources = new HashMap<String, Tile>();
        for (int i=0; i<mSourceLayer.mTiles.size(); i++)
        {
            Tile tile = mSourceLayer.mTiles.get(i);

            // reset isGrown!
            tile.isGrown = false;
            if (tile.hasAttribute("MAP_GrowProbability"))
            {
                String type = tile.getAttributeString("MAP_Type");
                String subtype = tile.getAttributeString("MAP_SubType");
                if (type==null) continue;
                if (subtype==null) continue;
                String key = type+"|"+subtype;
                if (sources.get(key)!=null) continue;
                sources.put(key, tile);
                if (sourcesString.length()!=0)
                    sourcesString +=", ";
                sourcesString +=key;
            }
        }
        if (updateUI)
            jTextFieldSources.setText(sourcesString);
        return sources;
    }

    public void setLayer(Layer nLayer)
    {
        mLayer = nLayer;
    }
    
    private void resetConfigPool(boolean select, String klasseToSet) /* allneeded*/
    {
        mClassSetting++;
        Collection<String> collectionKlasse = mTileGrowthDataPool.getKlassenHashMap().values();
        Iterator<String> iterKlasse = collectionKlasse.iterator();
        int i = 0;
        String klasse = "";

        jComboBoxKlasse.removeAllItems();
        while (iterKlasse.hasNext())
        {
            String item = iterKlasse.next();
            jComboBoxKlasse.addItem(item);
            if (select)
            {
                if (klasseToSet.length()==0)
                {
                    if (i==0)
                    {
                        jComboBoxKlasse.setSelectedIndex(i);
                        jTextFieldKlasse.setText(item);
                        klasse = item;
                    }
                }
                else
                {
                    if (klasseToSet.equalsIgnoreCase(item))
                    {
                        jComboBoxKlasse.setSelectedIndex(i);
                        jTextFieldKlasse.setText(item);
                        klasse = item;
                    }
                }
            }
            i++;
        }
        if ((select) && (klasse.length()==0))
        {
            if (jComboBoxKlasse.getItemCount()>0)
            {
                jComboBoxKlasse.setSelectedIndex(0);
                jTextFieldKlasse.setText(jComboBoxKlasse.getSelectedItem().toString());
                klasse = jComboBoxKlasse.getSelectedItem().toString();
            }
        }
        if (!select)  jComboBoxKlasse.setSelectedIndex(-1);

        Collection<TileGrowthData> colC = mTileGrowthDataPool.getMapForKlasse(klasse).values();
        Iterator<TileGrowthData> iterC = colC.iterator();

        jComboBoxName.removeAllItems();
        i = 0;
        while (iterC.hasNext())
        {
            TileGrowthData item = iterC.next();
            jComboBoxName.addItem(item.mName);
            if ((i==0) && (select))
            {
                jComboBoxName.setSelectedIndex(0);
                mTileGrowthData = mTileGrowthDataPool.get(item.mName);
                setAllFromCurrent();
            }
            i++;
        }
        if (!select)  jComboBoxName.setSelectedIndex(-1);
        mClassSetting--;
    }

    private void clearAll() /* allneeded*/
    {
        mClassSetting++;
        mTileGrowthData = new TileGrowthData();
        setAllFromCurrent();
        mClassSetting--;
    }

    private void setAllFromCurrent() /* allneeded*/
    {
        if (mTileGrowthData==null) return;
        mClassSetting++;
        jComboBoxKlasse.setSelectedItem(mTileGrowthData.mClass);
        jTextFieldKlasse.setText(mTileGrowthData.mClass);
        jComboBoxName.setSelectedItem(mTileGrowthData.mName);
        jTextFieldName.setText(mTileGrowthData.mName);

        mCurrentList.classNames.clear();
        mCurrentList.fileNames.clear();
        for(int i=0; i< mTileGrowthData.mTileCollectionFilename.size(); i++)
        {
            mCurrentList.fileNames.add(mTileGrowthData.mTileCollectionFilename.elementAt(i));
            mCurrentList.classNames.add(mTileGrowthData.mTileCollectionClass.elementAt(i));
        }
        
        jTable1.tableChanged(null);
        invalidate();
        validate();
        repaint();
        mClassSetting--;
    }

    private void readAllToCurrent() /* allneeded*/
    {
        mTileGrowthData.mClass = jTextFieldKlasse.getText();
        mTileGrowthData.mName = jTextFieldName.getText();

        mTileGrowthData.mTileCollectionFilename.clear();
        mTileGrowthData.mTileCollectionClass.clear();
        for(int i=0; i< mCurrentList.fileNames.size(); i++)
        {
            mTileGrowthData.mTileCollectionFilename.addElement(mCurrentList.fileNames.get(i));
            mTileGrowthData.mTileCollectionClass.addElement(mCurrentList.classNames.get(i));
        }
    }



    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jPanel4 = new javax.swing.JPanel();
        jPanel5 = new javax.swing.JPanel();
        jPanel18 = new javax.swing.JPanel();
        jScrollPane10 = new javax.swing.JScrollPane();
        jPanelIMageCollection2 = new javax.swing.JPanel();
        jPanel19 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jButtonFileSelect1 = new javax.swing.JButton();
        jTextFieldTileFile = new javax.swing.JTextField();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        jComboBoxTileKlasse = new javax.swing.JComboBox();
        jButton17 = new javax.swing.JButton();
        jButton18 = new javax.swing.JButton();
        jPanel3 = new javax.swing.JPanel();
        jComboBoxKlasse = new javax.swing.JComboBox();
        jComboBoxName = new javax.swing.JComboBox();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jTextFieldName = new javax.swing.JTextField();
        jTextFieldKlasse = new javax.swing.JTextField();
        jButtonNew = new javax.swing.JButton();
        jButtonSave = new javax.swing.JButton();
        jButtonSaveAsNew = new javax.swing.JButton();
        jButtonDelete = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jButtonExit = new javax.swing.JButton();
        jButtonGrow = new javax.swing.JButton();
        jTextFieldSources = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jButtonLoadSources = new javax.swing.JButton();

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 100, Short.MAX_VALUE)
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 100, Short.MAX_VALUE)
        );

        jPanel18.setBorder(javax.swing.BorderFactory.createTitledBorder("Tile Collection"));
        jPanel18.setAlignmentX(1.0F);

        jScrollPane10.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane10.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        jPanelIMageCollection2.setMinimumSize(new java.awt.Dimension(20, 20));
        jPanelIMageCollection2.setLayout(null);

        jPanel19.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel19.setPreferredSize(new java.awt.Dimension(52, 52));

        javax.swing.GroupLayout jPanel19Layout = new javax.swing.GroupLayout(jPanel19);
        jPanel19.setLayout(jPanel19Layout);
        jPanel19Layout.setHorizontalGroup(
            jPanel19Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 50, Short.MAX_VALUE)
        );
        jPanel19Layout.setVerticalGroup(
            jPanel19Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 50, Short.MAX_VALUE)
        );

        jPanelIMageCollection2.add(jPanel19);
        jPanel19.setBounds(5, 5, 52, 52);

        jScrollPane10.setViewportView(jPanelIMageCollection2);

        javax.swing.GroupLayout jPanel18Layout = new javax.swing.GroupLayout(jPanel18);
        jPanel18.setLayout(jPanel18Layout);
        jPanel18Layout.setHorizontalGroup(
            jPanel18Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel18Layout.createSequentialGroup()
                .addComponent(jScrollPane10, javax.swing.GroupLayout.PREFERRED_SIZE, 78, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, Short.MAX_VALUE))
        );
        jPanel18Layout.setVerticalGroup(
            jPanel18Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane10)
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Tile Selection"));

        jButtonFileSelect1.setText("...");
        jButtonFileSelect1.setMargin(new java.awt.Insets(0, 1, 0, -1));
        jButtonFileSelect1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonFileSelect1ActionPerformed(evt);
            }
        });

        jTextFieldTileFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jTextFieldTileFileActionPerformed(evt);
            }
        });
        jTextFieldTileFile.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                jTextFieldTileFileFocusLost(evt);
            }
        });

        jLabel6.setText("Filename");

        jLabel7.setText("Class");

        jComboBoxTileKlasse.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jComboBoxTileKlasseActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel6)
                    .addComponent(jLabel7))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addComponent(jTextFieldTileFile)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButtonFileSelect1))
                    .addComponent(jComboBoxTileKlasse, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jTextFieldTileFile, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel6)
                    .addComponent(jButtonFileSelect1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jComboBoxTileKlasse, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel7))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jButton17.setText("Add current tile collection");
        jButton17.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton17ActionPerformed(evt);
            }
        });

        jButton18.setText("remove selected");
        jButton18.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton18ActionPerformed(evt);
            }
        });

        jPanel3.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jComboBoxKlasse.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jComboBoxKlasseActionPerformed(evt);
            }
        });

        jComboBoxName.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jComboBoxNameActionPerformed(evt);
            }
        });

        jLabel3.setText("Name");

        jLabel4.setText("Class");

        jButtonNew.setText("New");
        jButtonNew.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonNewActionPerformed(evt);
            }
        });

        jButtonSave.setText("Save");
        jButtonSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonSaveActionPerformed(evt);
            }
        });

        jButtonSaveAsNew.setText("Save as new");
        jButtonSaveAsNew.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonSaveAsNewActionPerformed(evt);
            }
        });

        jButtonDelete.setText("Delete");
        jButtonDelete.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonDeleteActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel4)
                    .addComponent(jLabel3))
                .addGap(16, 16, 16)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jTextFieldName, javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jTextFieldKlasse, javax.swing.GroupLayout.Alignment.LEADING))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jComboBoxKlasse, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jComboBoxName, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jButtonSave)
                    .addComponent(jButtonNew))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jButtonSaveAsNew)
                    .addComponent(jButtonDelete))
                .addContainerGap())
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel3Layout.createSequentialGroup()
                        .addComponent(jButtonDelete)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jButtonSave)
                            .addComponent(jButtonSaveAsNew)))
                    .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                        .addGroup(jPanel3Layout.createSequentialGroup()
                            .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jComboBoxKlasse, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jButtonNew))
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(jComboBoxName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGroup(jPanel3Layout.createSequentialGroup()
                            .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jLabel4)
                                .addComponent(jTextFieldKlasse, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jLabel3)
                                .addComponent(jTextFieldName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        jTable1.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
        jTable1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jTable1MouseClicked(evt);
            }
        });
        jScrollPane1.setViewportView(jTable1);

        jButtonExit.setText("Exit");
        jButtonExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonExitActionPerformed(evt);
            }
        });

        jButtonGrow.setText("Grow with selected settings");
        jButtonGrow.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonGrowActionPerformed(evt);
            }
        });

        jLabel1.setText("Available sources:");

        jButtonLoadSources.setText("Reload sources");
        jButtonLoadSources.setEnabled(false);
        jButtonLoadSources.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonLoadSourcesActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
        jPanel5.setLayout(jPanel5Layout);
        jPanel5Layout.setHorizontalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(jPanel5Layout.createSequentialGroup()
                        .addComponent(jPanel18, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 190, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jTextFieldSources)
                    .addGroup(jPanel5Layout.createSequentialGroup()
                        .addComponent(jButtonGrow)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 19, Short.MAX_VALUE)
                        .addComponent(jButtonExit, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanel5Layout.createSequentialGroup()
                        .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jButton18, javax.swing.GroupLayout.PREFERRED_SIZE, 137, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jButton17)
                            .addGroup(jPanel5Layout.createSequentialGroup()
                                .addComponent(jLabel1)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButtonLoadSources)))
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel5Layout.setVerticalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel5Layout.createSequentialGroup()
                        .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel5Layout.createSequentialGroup()
                        .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel1)
                            .addComponent(jButtonLoadSources))
                        .addGap(4, 4, 4)
                        .addComponent(jTextFieldSources, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(27, 27, 27)))
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel18, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(jPanel5Layout.createSequentialGroup()
                        .addComponent(jButton18)
                        .addGap(40, 40, 40)
                        .addComponent(jButton17)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jButtonExit)
                            .addComponent(jButtonGrow)))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 125, Short.MAX_VALUE)))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents

    private void jButtonFileSelect1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonFileSelect1ActionPerformed
        InternalFrameFileChoser fc = new csa.gui.dialogs.InternalFrameFileChoser();
        fc.setCurrentDirectory(new java.io.File("xml"+File.separator+"Tile"));
        FileNameExtensionFilter  filter = new  FileNameExtensionFilter("xml", "xml");
        fc.setFileFilter(filter);
        int r = fc.showOpenDialog(Configuration.getConfiguration().getMainFrame());
        if (r != InternalFrameFileChoser.APPROVE_OPTION) return;
        String name = fc.getSelectedFile().getName();
        jTextFieldTileFile.setText(csa.util.UtilityString.replace(name, ".xml",""));
        jTextFieldTileFileActionPerformed(null);
    }//GEN-LAST:event_jButtonFileSelect1ActionPerformed

    private void jTextFieldTileFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextFieldTileFileActionPerformed
        loadTileCollection();
    }//GEN-LAST:event_jTextFieldTileFileActionPerformed
    public void loadTileCollection()
    {
        String file = jTextFieldTileFile.getText().trim();
        if (file.length() == 0) return;

        mTileDataPool = new TileDataPool("Tile"+File.separator+file+".xml");
        if (mTileDataPool == null) return;
        String _class = "";
        if (jComboBoxTileKlasse.getSelectedIndex() !=-1)
             _class = jComboBoxTileKlasse.getSelectedItem().toString().trim();
        resetTileConfigPool(true, _class, "");
    }

    // Config Pool for TileMap
    private void resetTileConfigPool(boolean select, String klasseToSet, String tileToSet) /* allneeded*/
    {
        mClassSetting++;
        jComboBoxTileKlasse.removeAllItems();
        mClassSetting--;

        if (mTileDataPool == null) return;

        mClassSetting++;
        Collection<String> collectionKlasse = mTileDataPool.getKlassenHashMap().values();
        Iterator<String> iterKlasse = collectionKlasse.iterator();
        int i = 0;
        String klasse = "";

        while (iterKlasse.hasNext())
        {
            String item = iterKlasse.next();
            jComboBoxTileKlasse.addItem(item);
            if (select)
            {
                if (klasseToSet.length()==0)
                {
                    if (i==0)
                    {
                        jComboBoxTileKlasse.setSelectedIndex(i);
                        klasse = item;
                    }
                }
                else
                {
                    if (klasseToSet.equalsIgnoreCase(item))
                    {
                        jComboBoxTileKlasse.setSelectedIndex(i);
                        klasse = item;
                    }
                }
            }
            i++;
        }
        if ((select) && (klasse.length()==0))
        {
            if (jComboBoxTileKlasse.getItemCount()>0)
            {
                jComboBoxTileKlasse.setSelectedIndex(0);
                klasse = jComboBoxTileKlasse.getSelectedItem().toString();
            }
        }
        if (!select)  jComboBoxTileKlasse.setSelectedIndex(-1);

        mClassSetting--;

        resetTileList(tileToSet);
    }
    String getTileClass()
    {
        String _class  = "";
        if (jComboBoxTileKlasse.getSelectedIndex()!=-1)
            _class  = jComboBoxTileKlasse.getSelectedItem().toString();
        return _class;
    }

    ImageSequenceData getImageSequenceDataForTile(TileData tileData)
    {
        if (tileData.getImageDataFile().trim().length()==0) return null;

        String imageFilename = "Graphics"+File.separator+tileData.getImageDataFile()+".xml";
        ImageSequenceDataPool imagePool = new ImageSequenceDataPool(imageFilename);
        if (imagePool == null) return null;
        String nameToSet = tileData.getImageDataName();

        return imagePool.get(nameToSet);
    }
    void resetTileList(String selectName)
    {
        mAllTilesInClass = new Vector <TileData>();

        String _class = getTileClass();

        if (mTileDataPool == null) return;

        Collection<TileData> colDk = mTileDataPool.getMapForKlasse(_class).values();
        Iterator<TileData> iterDk = colDk.iterator();
        /** Sorting */  Vector<String> names = new Vector<String>();
        while (iterDk.hasNext())
        {
            TileData deck = iterDk.next();
            mAllTilesInClass.addElement(deck);
            names.addElement(deck.mName);

        }
        Collections.sort(names, new Comparator<String>() {@Override
                public int compare(String s1, String s2) { return s1.compareTo(s2); } });
        Collections.sort(mAllTilesInClass, new Comparator<TileData>() {@Override
            public int compare(TileData s1, TileData s2) { return s1.mName.compareTo(s2.mName); } });
        setAllTiles(selectName);
    }
    
    HashMap <String, CompositeTile> compositeTileCache = new HashMap <String, CompositeTile>();
    private void resetCompositeCache()
    {
        compositeTileCache.clear();
    }
    private CompositeTile getCompositeTile(TileData tileData)
    {
        String key = tileData.getCompositeFile()+tileData.mName;
        CompositeTile ret = compositeTileCache.get(key);
        if (ret == null)
        {
            ret = new CompositeTile(tileData);
            compositeTileCache.put(key, ret);
        }
        
        return ret;
    }

    void setAllTiles(String selectName)
    {
        jPanelIMageCollection2.removeAll();

        int selected = 0;
        for (int t = 0; t < mAllTilesInClass.size(); t++)
        {
            TileData tileData = mAllTilesInClass.elementAt(t);
            if (tileData.mName.equals(selectName))
            {
                selected = t;
                break;
            }
        }
        
        int x = 5;
        int y = 5;
        for (int t = 0; t < mAllTilesInClass.size(); t++)
        {
            TileData tileData = mAllTilesInClass.elementAt(t);
            // jPanelIMageCollection1

            ImageSequenceData iSData = getImageSequenceDataForTile(tileData);
            String name = tileData.mName;

            JPanel ipanel = new JPanel();

            ipanel.setName(""+name);
            ipanel.setPreferredSize(new java.awt.Dimension(52, 52));
            ipanel.setLayout(new BorderLayout());

            ImageComponent mip = new ImageComponent();
            ipanel.add(mip, BorderLayout.CENTER);

            ipanel.setBounds(x, y, 52, 52);
            jPanelIMageCollection2.add(ipanel);
            if (iSData != null)
            {
                Vector <BaseImageData> data = BaseImageData.toBase(iSData);
                if (data.size()>0)
                {
                    Vector<Image> images = new Vector<Image>();
                    for (int i = 0; i < data.size(); i++)
                    {
                        BaseImageData baseImageData = data.elementAt(i);
                        images.addElement(baseImageData.image);
                    }
                    mip.setSequence(new ImageSequence(iSData));
                    mip.setDelay(iSData.getDelay());
                }
            }
            else
            {
                if (tileData.getIsCompositeTile())
                {
                    CompositeTile ctile =  getCompositeTile(tileData);
                    BufferedImage bimg = ctile.getImage(52,52);
                    //BufferedImage bimg = ctile.getImage(300,300);
                    mip.setImage(bimg);
                }
            }
            
            y += 52;
            y += 5;
            mip.setScaled(true, 52, 52);
            mip.setVisible(true);
        }

        jPanelIMageCollection2.setBounds(0,0,62,y);
        jPanelIMageCollection2.setPreferredSize(new Dimension(62,y));
        jPanelIMageCollection2.invalidate();
        jPanelIMageCollection2.validate();
        jPanelIMageCollection2.repaint();


        repaint();
        // TODO
    }
    private void jTextFieldTileFileFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jTextFieldTileFileFocusLost
        // if enabled, switching to another tab also loses focus
        //jTextFieldTileFileActionPerformed(null);
    }//GEN-LAST:event_jTextFieldTileFileFocusLost

    private void jComboBoxTileKlasseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBoxTileKlasseActionPerformed
        if (mClassSetting >0 ) return;
        mClassSetting++;
        String selected = jComboBoxTileKlasse.getSelectedItem().toString();
        resetTileConfigPool(true, selected, "");
        mClassSetting--;
    }//GEN-LAST:event_jComboBoxTileKlasseActionPerformed

    private void jComboBoxKlasseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBoxKlasseActionPerformed
        if (mClassSetting >0 ) return;
        mClassSetting++;;

        String selected = jComboBoxKlasse.getSelectedItem().toString();
        clearAll();
        resetConfigPool(true, selected);
        jTextFieldKlasse.setText(jComboBoxKlasse.getSelectedItem().toString());
        String key = jComboBoxName.getSelectedItem().toString();
        mTileGrowthData = mTileGrowthDataPool.get(key);
        setAllFromCurrent();
        mClassSetting--;
    }//GEN-LAST:event_jComboBoxKlasseActionPerformed

    private void jComboBoxNameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBoxNameActionPerformed
        if (mClassSetting > 0 ) return;
        String key = jComboBoxName.getSelectedItem().toString();
        mTileGrowthData = mTileGrowthDataPool.get(key);
        setAllFromCurrent();
    }//GEN-LAST:event_jComboBoxNameActionPerformed

    private void jButtonNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonNewActionPerformed
        mClassSetting++;
        mTileGrowthData = new TileGrowthData();
        clearAll();
        resetConfigPool(false, "");
        mClassSetting--;
    }//GEN-LAST:event_jButtonNewActionPerformed

    private void jButtonSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonSaveActionPerformed

        readAllToCurrent();
        mTileGrowthDataPool.put(mTileGrowthData);
        mTileGrowthDataPool.save();
        mClassSetting++;
        String klasse = jTextFieldKlasse.getText();
        resetConfigPool(true, klasse);
        jComboBoxName.setSelectedItem(mTileGrowthData.mName);
        mClassSetting--;
    }//GEN-LAST:event_jButtonSaveActionPerformed

    private void jButtonSaveAsNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonSaveAsNewActionPerformed
        mTileGrowthData = new TileGrowthData();
        readAllToCurrent();
        mTileGrowthDataPool.putAsNew(mTileGrowthData);
        mTileGrowthDataPool.save();
        mClassSetting++;
        String klasse = jTextFieldKlasse.getText();
        resetConfigPool(true,klasse);
        jComboBoxName.setSelectedItem(mTileGrowthData.mName);
        mClassSetting--;
    }//GEN-LAST:event_jButtonSaveAsNewActionPerformed

    private void jButtonDeleteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonDeleteActionPerformed
        readAllToCurrent();
        mTileGrowthDataPool.remove(mTileGrowthData);
        mTileGrowthDataPool.save();
        mClassSetting++;
        String klasse = jTextFieldKlasse.getText();
        resetConfigPool(true,klasse);

        if (jComboBoxName.getSelectedIndex() == -1)
        {
            clearAll();
        }

        String key = jComboBoxName.getSelectedItem().toString();
        mTileGrowthData = mTileGrowthDataPool.get(key);
        setAllFromCurrent();

        mClassSetting--;
    }//GEN-LAST:event_jButtonDeleteActionPerformed

    private void jButton17ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton17ActionPerformed
        if (jTextFieldTileFile.getText().length() == 0) return;
        if (jComboBoxTileKlasse.getSelectedIndex() == -1) return;
        
        String key = jTextFieldTileFile.getText()+jComboBoxTileKlasse.getSelectedItem().toString();
        for (int i=0; i<mCurrentList.fileNames.size(); i++ )
        {
            String k =mCurrentList.fileNames.get(i)+mCurrentList.classNames.get(i);
            if (k.equals(key))
            {
                // dont add same tilecollection twice!
                return;
            }
        }

        mCurrentList.fileNames.add(jTextFieldTileFile.getText());
        mCurrentList.classNames.add(jComboBoxTileKlasse.getSelectedItem().toString());
        jTable1.tableChanged(null);
        invalidate();
        validate();
        repaint();
    }//GEN-LAST:event_jButton17ActionPerformed

    private void jButton18ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton18ActionPerformed
        

        int[] rows = jTable1.getSelectedRows();
        if (rows.length == 0) {
            return;
        }

        Vector<String> toDelete = new Vector<String>();
        for (int i = rows.length - 1; i >= 0; i--) 
        {
            String key = mCurrentList.fileNames.get(i)+mCurrentList.classNames.get(i);
            toDelete.addElement(key);
        }

        for (int i = 0; i < toDelete.size(); i++) 
        {
            String key = toDelete.elementAt(i);
            for (int c=0; i<mCurrentList.fileNames.size(); c++ )
            {
                String k =mCurrentList.fileNames.get(c)+mCurrentList.classNames.get(c);
                if (k.equals(key))
                {
                    mCurrentList.classNames.remove(mCurrentList.classNames.get(c));
                    mCurrentList.fileNames.remove(mCurrentList.fileNames.get(c));
                    break;
                }
            }

        }
        jTable1.tableChanged(null);
        invalidate();
        validate();
        repaint();
    }//GEN-LAST:event_jButton18ActionPerformed

    private void jButtonExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonExitActionPerformed
        mMPParent.growTilesExit(this);
    }//GEN-LAST:event_jButtonExitActionPerformed

    HashMap<String, Integer> singletonCounter = new HashMap<String, Integer>();
    private void jButtonGrowActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonGrowActionPerformed

        poolCash = new HashMap<String, TileDataPool>();
        tileCache = new HashMap<String, TileData>();
        growTileCash = new HashMap <String, Vector<Tile>>();
        
        HashMap<String, Tile> sourcesCombinations = getSources(); // in "type|subtype"
        singletonCounter = new HashMap<String, Integer>();
        // fillSingletons();

        int i = Global.getRand().nextInt(mSourceLayer.mTiles.size());
        // todo
        for (int c=0; c<mSourceLayer.mTiles.size(); c++)
        {
            i = (i+1)%(mSourceLayer.mTiles.size());

            String key = "";
            Tile tile = mSourceLayer.mTiles.get(i);

            if (tile.isGrown) continue;
            String type = tile.getAttributeString("MAP_Type");
            String subtype = tile.getAttributeString("MAP_SubType");
            if (type!=null) 
                if (subtype!=null) 
                    key = type+"|"+subtype;

            if(sourcesCombinations.get(key) == null) continue;
            
            int prob = tile.getAttributeInt("MAP_GrowProbability");
            int randomPercent = csa.Global.getRand().nextInt(100)+1; // from 1 to 100 both inklusive
            if (randomPercent>prob) continue;
            
            // now the source tile "allows" growing
            // check what new tiles might be grown!
            // this is only a test for type / subtype
            // singletons, borders and parent sizes
            // must still be checked!
            Vector<Tile> possibleGrowTiles = getGrowTiles(tile);
            if (possibleGrowTiles.size()<=0) continue;

            // edits vector of tiles, to allow only
            // tiles which have parental permssions
            // also adjusts accumulatedProbabilityGrowing
            checkParentSizes(possibleGrowTiles, tile);
            if (possibleGrowTiles.size()<=0) continue;
            
            // edits vector of tiles, to allow only
            // tiles which have parental permssions
            // also adjusts accumulatedProbabilityGrowing
            checkSingletons(possibleGrowTiles, tile);
            if (possibleGrowTiles.size()<=0) continue;
            
            // edits vector of tiles, to allow only
            // tiles which have parental permssions
            // also adjusts accumulatedProbabilityGrowing
            checkBorders(possibleGrowTiles, tile);
            if (possibleGrowTiles.size()<=0) continue;
            
            
            int maxProb = possibleGrowTiles.elementAt(possibleGrowTiles.size()-1).accumulatedProbabilityGrowing;
            int randomTile = csa.Global.getRand().nextInt(maxProb);
            
            Tile toGrow=null;
            for (int t=0; t<possibleGrowTiles.size(); t++)
            {
                if (randomTile<=possibleGrowTiles.elementAt(t).accumulatedProbabilityGrowing)
                {
                    toGrow = possibleGrowTiles.elementAt(t);
                    break;
                }
            }
            if (toGrow == null) continue;
            
            // NOW we have a tile we can actually place!
            // build a new tile!
            TileData growData = getTile(toGrow.getData().getTileSetFileName(), toGrow.getData().getName());
            
            int number = 1;
            if (toGrow.hasAttribute("MAP_GrowNumber"))
            {
                number = toGrow.getAttributeInt("MAP_GrowNumber");
            }
            boolean overborder = false;
            if (toGrow.hasAttribute("MAP_Overborder"))
            {
                overborder = toGrow.getAttributeBool("MAP_Overborder");
            }

            //check singleton - and add it to hashmap

            int max = toGrow.getAttributeInt("MAP_MaxGrowPerMap");
            if (max!=0)
            {
                String kkey = toGrow.getData().getTileSetFileName() +"_"+ toGrow.getData().mName;
                Integer counting = singletonCounter.get(kkey);
                if (counting == null) counting = 0;
                counting++;
                singletonCounter.put(key, counting);
            }

            //check parent position - and adjust pos
            int offsetX=0;
            int offsetY=0;
            String parentOffset = toGrow.getAttributeString("MAP_ParentZeroOffset");
            if (parentOffset != null) 
            {
                Vector<Integer> iv = csa.util.UtilityString.intVector(parentOffset, ",");
                if (iv.size()>=2) 
                {
                    offsetX = iv.elementAt(0);
                    offsetY = iv.elementAt(1);
                }
            }
            
            // for composite tiles:
            // only grown if number == 1
            if (number == 1)
            {
                int x = tile.getX()+tile.getMaxWidthUnscaled()/2;
                int y = tile.getY()+tile.getMaxHeightUnscaled()/2;

                
                //to center i Need the new tiles width and height
                x -= toGrow.getMaxWidthUnscaled()/2;
                y -= toGrow.getMaxHeightUnscaled()/2;

                if (!((offsetX==0) && (offsetY==0)))
                {
                    x = tile.getX()+offsetX;
                    y = tile.getY()+offsetY;
                }
                
                System.out.println("Grow on Tile: "+tile+" "+tile.getX()+", "+tile.getY());
                // with variants if possible
                mLayer.addTile(growData, x, y , true, getPool("Tile"+File.separator+toGrow.getData().getTileSetFileName()+".xml"));
            
            }
            else // add a number of tiles
            {
                int minX = tile.getX();
                int minY = tile.getY();
                int maxX = minX+tile.getMaxWidthUnscaled()-toGrow.getMaxWidthUnscaled();
                int maxY = minY+tile.getMaxHeightUnscaled()-toGrow.getMaxHeightUnscaled();
                if (overborder)
                {
                    minX = tile.getX()-toGrow.getMaxWidthUnscaled();
                    minY = tile.getY()-toGrow.getMaxHeightUnscaled();
                    maxX = minX+tile.getMaxWidthUnscaled()+toGrow.getMaxWidthUnscaled();
                    maxY = minY+tile.getMaxHeightUnscaled()+toGrow.getMaxHeightUnscaled();;
                }
                else
                {
                    // maxX = minX+tile.getMaxWidthUnscaled()-toGrow.getMaxWidthUnscaled();
                    // maxY = minY+tile.getMaxHeightUnscaled()-toGrow.getMaxHeightUnscaled();
                }
                int difX = maxX - minX; 
                int difY = maxY - minY;
                
                for(int r = 0; r<number; r++)
                {
                    int x = minX+Global.getRand().nextInt(difX);
                    int y = minY+Global.getRand().nextInt(difY);

                    // with variants if possible
                    mLayer.addTile(growData, x, y , true, getPool("Tile"+File.separator+toGrow.getData().getTileSetFileName()+".xml"));
                }
                
            }
            tile.isGrown = true;
            setSizesGrown(toGrow, tile);

            System.out.println("Tile placed!");
        }
        
        mSuccessfull = true;
        if (mLayer.mTiles.size()>0)
            mMPParent.growTilesDone(this, mLayer);
    }//GEN-LAST:event_jButtonGrowActionPerformed

    HashMap <String, Vector<Tile>> growTileCash = new HashMap <String, Vector<Tile>>();
    Vector<Tile> getGrowTiles(Tile sourceTile)
    {
        String key = sourceTile.getData().getTileSetFileName()+sourceTile.getData().getCClass()+sourceTile.getData().getName();
        Vector<Tile> ret = growTileCash.get(key);
        if (ret != null) return ret;
        ret = new Vector<Tile>();

        if (sourceTile.getAttribute("MAP_SUBTYPE").toUpperCase().equals("ISLAND"))
        {
            System.out.println("Buh!");
        }
        
        String stype = sourceTile.getAttribute("MAP_TYPE");
        String ssubtype = sourceTile.getAttribute("MAP_SUBTYPE");
        int accumulatedProbabilityGrowing = 0; 

        // build it
        // go thru all included tile collections and collect tiles
        // which fit the type and subtype!
        for (int i=0; i<mCurrentList.fileNames.size(); i++)
        {
            TileDataPool localTileDataPool = getPool("Tile"+File.separator+mCurrentList.fileNames.get(i) +".xml");
            if (localTileDataPool == null) continue;
            HashMap<String, TileData> tileMap = localTileDataPool.getMapForKlasse(mCurrentList.classNames.get(i));
            
            Set entries = tileMap.entrySet();
            Iterator it = entries.iterator();
            while (it.hasNext())
            {
                Map.Entry entry = (Map.Entry) it.next();
                Tile tile = new Tile((TileData) entry.getValue());
                String nType = tile.getAttribute("MAP_NEEDSTYPE");
                String[] nSubType = tile.getAttributes("MAP_NEEDSSUBTYPE");
                if (nType==null) continue;
                if (nSubType==null) continue;
                if (nSubType.length==0) continue;
                if (nType.equalsIgnoreCase(stype))
                {
                    for (int s=0; s< nSubType.length; s++)
                    {
                        if (nSubType[s].equalsIgnoreCase(ssubtype))
                        {
                            accumulatedProbabilityGrowing += tile.getAttributeInt("MAP_GrowProbability"); 
                            tile.accumulatedProbabilityGrowing = accumulatedProbabilityGrowing;
                            ret.addElement(tile);
                        }
                    }
                }
            }

        }
        
        growTileCash.put(key, ret);
        return ret;
    }


    private void setSameTileOnRelativePosition(Tile toGrowOn, int rx ,int ry)
    {
        int tileWidth = toGrowOn.getMaxWidth();
        int tileHeight = toGrowOn.getMaxWidth();
        
        rx *= tileWidth;
        ry *= tileHeight;
        int x = toGrowOn.getX() + rx;
        int y = toGrowOn.getY() + ry;
        
        Tile found = mSourceLayer.isTileOnPosition(x, y);
        
        if (found == null) return;
        found.isGrown = true;
    }
    
        
    // returns true if the tile on the relative tile pos is the same type/subtype as the provided one!
    private boolean checkSameTileOnRelativePosition(Tile toGrowOn, int rx ,int ry)
    {
        int tileWidth = toGrowOn.getMaxWidth();
        int tileHeight = toGrowOn.getMaxWidth();
        
        rx *= tileWidth;
        ry *= tileHeight;
        int x = toGrowOn.getX() + rx;
        int y = toGrowOn.getY() + ry;
        
        Tile found = mSourceLayer.isTileOnPosition(x, y);
        if (found == null) return false;
        String ftype = found.getAttribute("MAP_TYPE");
        String fsubtype = found.getAttribute("MAP_SUBTYPE");

        if (ftype == null) return false;
        if (fsubtype == null) return false;
        
        if (ftype.length()==0) return false;
        if (fsubtype.length()==0) return false;

        String stype = toGrowOn.getAttribute("MAP_TYPE");
        String ssubtype = toGrowOn.getAttribute("MAP_SUBTYPE");
        
        return ((ftype.equals(stype)) && (fsubtype.equals(ssubtype)));
    }
    
    boolean checkNeightbourType(Tile toGrowOn, String neighbourType, String neighbourSubType)
    {
        boolean ret = false;
        int tileWidth = toGrowOn.getMaxWidth();
        int tileHeight = toGrowOn.getMaxWidth();
        
        int x = toGrowOn.getX();
        int y = toGrowOn.getY();
        
        // North
        Tile found = mSourceLayer.isTileOnPosition(x, y-tileHeight);
        if (found != null)
        {
            String ftype = found.getAttribute("MAP_TYPE");
            String fsubtype = found.getAttribute("MAP_SUBTYPE");
            if ((neighbourType.equals(ftype)) && ((neighbourSubType.equals(fsubtype))))
                return true;
        }
        // South
        found = mSourceLayer.isTileOnPosition(x, y+tileHeight);
        if (found != null)
        {
            String ftype = found.getAttribute("MAP_TYPE");
            String fsubtype = found.getAttribute("MAP_SUBTYPE");
            if ((neighbourType.equals(ftype)) && ((neighbourSubType.equals(fsubtype))))
                return true;
        }
        // East
        found = mSourceLayer.isTileOnPosition(x+tileWidth, y);
        if (found != null)
        {
            String ftype = found.getAttribute("MAP_TYPE");
            String fsubtype = found.getAttribute("MAP_SUBTYPE");
            if ((neighbourType.equals(ftype)) && ((neighbourSubType.equals(fsubtype))))
                return true;
        }
        // West
        found = mSourceLayer.isTileOnPosition(x-tileWidth, y);
        if (found != null)
        {
            String ftype = found.getAttribute("MAP_TYPE");
            String fsubtype = found.getAttribute("MAP_SUBTYPE");
            if ((neighbourType.equals(ftype)) && ((neighbourSubType.equals(fsubtype))))
                return true;
        }
        // North-West
        found = mSourceLayer.isTileOnPosition(x-tileWidth, y-tileHeight);
        if (found != null)
        {
            String ftype = found.getAttribute("MAP_TYPE");
            String fsubtype = found.getAttribute("MAP_SUBTYPE");
            if ((neighbourType.equals(ftype)) && ((neighbourSubType.equals(fsubtype))))
                return true;
        }
        // North-East
        found = mSourceLayer.isTileOnPosition(x+tileWidth, y-tileHeight);
        if (found != null)
        {
            String ftype = found.getAttribute("MAP_TYPE");
            String fsubtype = found.getAttribute("MAP_SUBTYPE");
            if ((neighbourType.equals(ftype)) && ((neighbourSubType.equals(fsubtype))))
                return true;
        }
        // South-West
        found = mSourceLayer.isTileOnPosition(x-tileWidth, y+tileHeight);
        if (found != null)
        {
            String ftype = found.getAttribute("MAP_TYPE");
            String fsubtype = found.getAttribute("MAP_SUBTYPE");
            if ((neighbourType.equals(ftype)) && ((neighbourSubType.equals(fsubtype))))
                return true;
        }
        // South-East
        found = mSourceLayer.isTileOnPosition(x+tileWidth, y+tileHeight);
        if (found != null)
        {
            String ftype = found.getAttribute("MAP_TYPE");
            String fsubtype = found.getAttribute("MAP_SUBTYPE");
            if ((neighbourType.equals(ftype)) && ((neighbourSubType.equals(fsubtype))))
                return true;
        }
        return ret;
    }
    
    void setSizesGrown(Tile growTile, Tile sourceTile)
    {
        boolean ret = false;
        Vector<Tile> removeTiles = new Vector<Tile>();
        
        {
            String s = growTile.getAttributeString("MAP_ParentMinSize");
            if (s == null) return;
            Vector<Integer> iv = csa.util.UtilityString.intVector(s, "x");
            
            if (iv.size()<2) return;

            int width = iv.elementAt(0);
            int height = iv.elementAt(1);

            for (int h=0; h<height; h++)
            {
                for (int w=0; w<width; w++)
                {
                    setSameTileOnRelativePosition(sourceTile, w ,h);
                }
            }
        }
    }
    
    // edits vector of tiles, to allow only
    // tiles which have parental permssions
    // also adjusts accumulatedProbabilityGrowing
    boolean checkParentSizes(Vector<Tile> possibleGrowTiles, Tile toGrowOn)
    {
        boolean ret = false;
        Vector<Tile> removeTiles = new Vector<Tile>();
        
        for (int i = 0; i < possibleGrowTiles.size(); i++) 
        {
            Tile growTile = possibleGrowTiles.elementAt(i);
            String s = growTile.getAttributeString("MAP_ParentMinSize");
            if (s == null) continue;
            Vector<Integer> iv = csa.util.UtilityString.intVector(s, "x");
            if (iv.size()<2) continue;
            int width = iv.elementAt(0);
            int height = iv.elementAt(1);
            boolean sizeOk = true;
            for (int h=0; h<height; h++)
            {
                for (int w=0; w<width; w++)
                {
                    sizeOk &= checkSameTileOnRelativePosition(toGrowOn, w ,h);
                }
            }
            if (!sizeOk)
            {
                removeTiles.addElement(growTile);
                System.out.println("Parent Size Check failed for: "+growTile);
                continue;
            }
            System.out.println("Parent Size Check successfull for: "+growTile);
        }
        
        for (int i = 0; i < removeTiles.size(); i++) 
        {
            possibleGrowTiles.remove(removeTiles.elementAt(i));
            ret = true;
        }
        if (ret) adjustAccumulatedGrowing(possibleGrowTiles);
        return ret;
    }
    /*
     * NOT POSSIBLE!
     * Since each growth is build on a NEW layer!
     * 
        singletonCounter = new HashMap<String, Integer>();
    private void fillSingletons()
    {
        for (int i=0; i<mSourceLayer.mTiles.size(); i++)
        {
            Tile tile = mSourceLayer.mTiles.get(i);
            int max = tile.getAttributeInt("MAP_MaxGrowPerMap");
            if (max==0) continue;

            String kkey = toGrow.getData().getTileSetFileName() +"_"+ toGrow.getData().mName;
            Integer counting = singletonCounter.get(kkey);
            if (counting == null) counting = 0;
            counting++;
            singletonCounter.put(key, counting);
        
        
        }        
    }
    */
    // edits vector of tiles, to allow only
    // tiles which have parental permssions
    // also adjusts accumulatedProbabilityGrowing
    boolean checkSingletons(Vector<Tile> possibleGrowTiles, Tile toGrowOn)
    {
        boolean ret = false;
        Vector<Tile> removeTiles = new Vector<Tile>();
        for (int i = 0; i < possibleGrowTiles.size(); i++) 
        {
            Tile growTile = possibleGrowTiles.elementAt(i);
            int max = growTile.getAttributeInt("MAP_MaxGrowPerMap");
            if (max==0) continue;
            String key = growTile.getData().getTileSetFileName() +"_"+ growTile.getData().mName;
            Integer counting = singletonCounter.get(key);
            if (counting == null) continue;
            if (counting>=max)
            {
                removeTiles.addElement(growTile);
                System.out.println("Singleton Check failed for: "+growTile);
                continue;
            }
            System.out.println("Singleton Check successfull for: "+growTile);
        }
        for (int i = 0; i < removeTiles.size(); i++) 
        {
            possibleGrowTiles.remove(removeTiles.elementAt(i));
            ret = true;
        }
        if (ret) adjustAccumulatedGrowing(possibleGrowTiles);
        return ret;
    }

    // edits vector of tiles, to allow only
    // tiles which have parental permssions
    // also adjusts accumulatedProbabilityGrowing
    boolean checkBorders(Vector<Tile> possibleGrowTiles, Tile toGrowOn)
    {
        boolean ret = false;
        Vector<Tile> removeTiles = new Vector<Tile>();

        
        //
        for (int i = 0; i < possibleGrowTiles.size(); i++) 
        {
            Tile growTile = possibleGrowTiles.elementAt(i);
            String neighbourType = growTile.getAttributeString("MAP_ParentNeighbourType");
            if (neighbourType == null) continue;
            if (neighbourType.length()==0) continue;
            String neighbourSubType = growTile.getAttributeString("MAP_ParentNeighbourSubType");
            if (neighbourSubType == null) continue;
            if (neighbourSubType.length()==0) continue;

            if (!checkNeightbourType(toGrowOn, neighbourType, neighbourSubType))
            {
                removeTiles.addElement(growTile);
                System.out.println("Border Check failed for: "+growTile);
                continue;
            }
            System.out.println("Border Check successfull for: "+growTile);
        }
        
        for (int i = 0; i < removeTiles.size(); i++) 
        {
            possibleGrowTiles.remove(removeTiles.elementAt(i));
            ret = true;
        }
        if (ret) adjustAccumulatedGrowing(possibleGrowTiles);
        return ret;
    }

     // vector is filled with NEW tiles
     void adjustAccumulatedGrowing(Vector<Tile> possibleGrowTiles)
     {
         Vector<Tile> newPossibleGrowTiles = new Vector<Tile>();
         int accumulatedProbabilityGrowing = 0; 
         for (int i = 0; i < possibleGrowTiles.size(); i++) 
         {
             Tile tile = new Tile(possibleGrowTiles.elementAt(i).getData(), false);
             accumulatedProbabilityGrowing += tile.getAttributeInt("MAP_GrowProbability"); 
             tile.accumulatedProbabilityGrowing = accumulatedProbabilityGrowing;
             newPossibleGrowTiles.add(tile);
         }
         possibleGrowTiles.clear();
         for (int i = 0; i < newPossibleGrowTiles.size(); i++) 
         {
             possibleGrowTiles.add(newPossibleGrowTiles.elementAt(i));
         }
     }
    
    
    private void jButtonLoadSourcesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonLoadSourcesActionPerformed
        setSources(true);
    }//GEN-LAST:event_jButtonLoadSourcesActionPerformed

    private void jTable1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTable1MouseClicked

        if ( evt.getClickCount() == 2 )
        {
            JTable table = (JTable) evt.getSource();
            int mRow = table.convertRowIndexToModel(table.rowAtPoint(evt.getPoint()));
            if (mRow <0) return;
            setSelectedTileSet(mCurrentList.fileNames.get(mRow), mCurrentList.classNames.get(mRow));
            
        }


    }//GEN-LAST:event_jTable1MouseClicked

    
    HashMap<String, TileDataPool> poolCash = new HashMap<String, TileDataPool>();

    TileDataPool getPool(String name)
    {
        TileDataPool pool = poolCash.get(name);
        if (pool == null)
        {
            pool = new TileDataPool(name);
            poolCash.put(name, pool);

        }
        return pool;
    }

    
    TileData getTile(String filename, String name)
    {
        TileData data = tileCache.get(filename+name);
        if ( data != null)
        {
            if ((data.getVariantNames().size()==0)  || (data.getVariantPercent()==0)) 
                return data;
        }
        TileDataPool localTileDataPool = getPool("Tile"+File.separator+filename+".xml");
        if (localTileDataPool == null) return null;

        if (data == null)
            data = localTileDataPool.get(name);
        
        if (data.getVariantNames().size()>0) 
        {
            int r = csa.Global.getRand().nextInt(100); // percent
            if (r<data.getVariantPercent())
            {
                int t = csa.Global.getRand().nextInt(data.getVariantNames().size()); // percent

                name = data.getVariantNames().elementAt(t);
                TileData data2 = tileCache.get(filename+name);
                if (data2 == null)
                    data2 = localTileDataPool.get(data.getVariantNames().elementAt(t));
                data = data2;
            }
        }
                
        tileCache.put(filename+name, data);
        return  data;
    }

    javax.swing.table.TableModel getTableModel()
    {
        AbstractTableModel model = new
         AbstractTableModel() {
            @Override public String getColumnName(int col)
            {
                if (col==0) return "Filename";
                if (col==1) return "Class";
                return "";
            }
             @Override
            public int getRowCount()
            {
                return mCurrentList.fileNames.size();
            }
             @Override
            public int getColumnCount() { return 2;}
             @Override
            public Object getValueAt(int row, int col)
            {
                if (col == 0)
                    return mCurrentList.fileNames.get(row);
                if (col == 1)
                    return mCurrentList.classNames.get(row);
                return "";
            }
            @Override public boolean isCellEditable(int row, int col)
            {
                return false;
            }
            @Override public Class getColumnClass(int col)
            {
                return String.class;
            }
        };
        return model;
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JButton jButton17;
    private javax.swing.JButton jButton18;
    private javax.swing.JButton jButtonDelete;
    private javax.swing.JButton jButtonExit;
    private javax.swing.JButton jButtonFileSelect1;
    private javax.swing.JButton jButtonGrow;
    private javax.swing.JButton jButtonLoadSources;
    private javax.swing.JButton jButtonNew;
    private javax.swing.JButton jButtonSave;
    private javax.swing.JButton jButtonSaveAsNew;
    private javax.swing.JComboBox jComboBoxKlasse;
    private javax.swing.JComboBox jComboBoxName;
    private javax.swing.JComboBox jComboBoxTileKlasse;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JPanel jPanel18;
    private javax.swing.JPanel jPanel19;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanelIMageCollection2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane10;
    private javax.swing.JTable jTable1;
    private javax.swing.JTextField jTextFieldKlasse;
    private javax.swing.JTextField jTextFieldName;
    private javax.swing.JTextField jTextFieldSources;
    private javax.swing.JTextField jTextFieldTileFile;
    // End of variables declaration//GEN-END:variables

    private void setSelectedTileSet(String filename, String className)
    {
        jTextFieldTileFile.setText(filename);
        loadTileCollection();
        jComboBoxTileKlasse.setSelectedItem(className);
    }
}
