package Cluedo.GUI2;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.StringTokenizer;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import Cluedo.API.CDialog;
import Cluedo.API.CardImage;
import Cluedo.API.CluedoConfig;
import Cluedo.API.LanguagePack;
import Cluedo.API.NameDictionary;
import Cluedo.API.Resources;
import Cluedo.Game.Card;
import Cluedo.Game.CardCollection;
import Cluedo.Game.Player;

public class SetupGame extends CDialog implements ActionListener {
    
    static final String HTML_ON = "<html><body>";
    static final String HTML_OFF = "</body></html>";
    static final String HTML_NEWLINE = "<br>";
    
    
    NameDictionary nameDictionary = new NameDictionary();
    
    CluedoConfig gameConfig = new CluedoConfig();

    
    // ------------------------------------
    // Rule selection panel
    
    JRadioButton rule1Button = null; 
    JRadioButton rule2Button = null;
    ButtonGroup ruleButtons = new ButtonGroup ();
    
    JButton selectTheseRules = null;
    
    JLabel ruleDescriptionLabel = null;    
    //
    
    // --------------------------------------
    // Map selection Panel
    // --------------------------------------
    
    CardImage []cardsHeld = null;
    CardImage mapImage = null;
    JList mapList ;
    String xmlMaps[];
    JTextArea mapInfo;
    JToggleButton applyButton;
    String mapName = "";
    JPanel picPanel;
    final static String mapFolder = "./Resources/Maps/";
    // --------------------------------------
    // end selection variables
    // --------------------------------------
    
    
    PlayerSelect playerSelect;
    private static final String DEFAULT_GROUP = "setup_game";
    
    public SetupGame(String args) {
        super(args, true);
        
        // Card set loaded before anything else
        gameConfig.setCardSet("default");
        gameConfig.loadCards();
        
        playerSelect = new PlayerSelect(gameConfig);

        
        JButton startButton = new JButton(LanguagePack.getString("start_game", DEFAULT_GROUP));
        JButton cancelButton = new JButton(LanguagePack.getString("cancel_game", DEFAULT_GROUP));
        
        startButton.addActionListener(this);
        startButton.setActionCommand("start_game");
        cancelButton.addActionListener(this);
        cancelButton.setActionCommand("cancel");
        
        getContentPane().add( new JLabel(LanguagePack.getString("main_help_message", DEFAULT_GROUP)), BorderLayout.NORTH );
      
       
        JTabbedPane tabbedPane = new JTabbedPane();
        
        tabbedPane.addTab(LanguagePack.getString("players_tab", DEFAULT_GROUP), playerSelect);
        tabbedPane.addTab(LanguagePack.getString("map_tab", DEFAULT_GROUP), createChooseMapPanel() );
        tabbedPane.addTab(LanguagePack.getString("suspects_tab", DEFAULT_GROUP), new SuspectSelect(gameConfig, playerSelect));
        tabbedPane.addTab(LanguagePack.getString("weapons_tab", DEFAULT_GROUP), new WeaponSelect(gameConfig));
        
        tabbedPane.addTab(LanguagePack.getString("rules_tab", DEFAULT_GROUP), buildGameRules());
        
        getContentPane().add(tabbedPane, BorderLayout.CENTER);
        
        create( new JButton[] {startButton, cancelButton}, -1, -1);
        
        centre();
        setVisible(true);
    }
    
    
    
    // Listeners for the game rules panel
    
    ActionListener selectRulesListener = new ActionListener () {
        public void actionPerformed(ActionEvent e) {
            int type = 0;

            if(rule1Button.isSelected() == true) {
                type = 0;
            }
            else if(rule2Button.isSelected() == true) {
                type = 1;
            }
                
            gameConfig.setGameType(type);
        }
        
        };
    ActionListener changeRuleListener = new ActionListener () {
      public void actionPerformed(ActionEvent e) {
          String newCaption = "";
          
          newCaption = addBreaks (LanguagePack.getString(e.getActionCommand() + "_detail", DEFAULT_GROUP));

          ruleDescriptionLabel.setText(newCaption);
      }
        
    };
    
    /**
     * @return
     */
    private JPanel buildGameRules() {
        JPanel content = new JPanel ();
        
        GridBagLayout grid = new GridBagLayout();
		GridBagConstraints c = new GridBagConstraints();
		content.setLayout(grid);


		String rule1 = LanguagePack.getString("regular_cluedo_rules", DEFAULT_GROUP);
		String rule2 = LanguagePack.getString("special_rolling_cluedo_rules", DEFAULT_GROUP);
		
		rule1Button = new JRadioButton(rule1);
		rule2Button= new JRadioButton(rule2);
		
		rule1Button.setActionCommand("regular_cluedo_rules");
		rule2Button.setActionCommand("special_rolling_cluedo_rules");
		
        rule1Button.addActionListener(changeRuleListener);
		rule2Button.addActionListener(changeRuleListener);
		
		rule1Button.setSelected(true);
		
		ruleButtons.add(rule1Button);
		ruleButtons.add(rule2Button);
		
		String rules_panel_message = LanguagePack.getString("rules_panel_message", DEFAULT_GROUP);
		
		String rule_description_title = LanguagePack.getString("rule_description_title", DEFAULT_GROUP);
		JLabel ruleDescriptionTitle = new JLabel (rule_description_title);
		
		JLabel caption = new JLabel(rules_panel_message);
		caption.setFont(new Font("Arial", Font.BOLD, 12));
		
		String rule_description = LanguagePack.getString("regular_cluedo_rules_detail", DEFAULT_GROUP);
		ruleDescriptionLabel = new JLabel(rule_description);
		ruleDescriptionLabel.setPreferredSize(new Dimension(400, 100));
		
		JScrollPane scroller = new JScrollPane(ruleDescriptionLabel);
		
		String select_these_rules = LanguagePack.getString("select_rules_button", DEFAULT_GROUP);
		selectTheseRules = new JButton(select_these_rules);
		selectTheseRules.addActionListener(selectRulesListener);
		
		c.anchor = GridBagConstraints.WEST;
		
		JLabel nothing = new JLabel();
		
		c.insets.bottom = 30;		
		c.weightx=2;
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.gridx=0;
		c.gridy=0;
		grid.setConstraints(nothing, c);
		
		c.insets.bottom = 20;
		c.weightx=1;
		c.gridx=0;
		c.gridy++;
		grid.setConstraints(rule1Button, c);

		c.weightx=1;
		c.gridx=0;
		c.gridy++;
		grid.setConstraints(rule2Button, c);

		c.insets.bottom = 10;
		c.weightx=1;
		c.gridx=0;
		c.gridy++;
		grid.setConstraints(ruleDescriptionTitle, c);		
		
		c.insets.bottom = 30;
		c.weightx=2;
		c.gridx=0;
		c.gridy++;
		grid.setConstraints(scroller, c);
		

		c.weightx=1;
		c.gridx=0;
		c.gridy++;
		grid.setConstraints(selectTheseRules, c);

		
		content.add(nothing);
		content.add(rule1Button);
		content.add(rule2Button);
		content.add(ruleDescriptionTitle);
		content.add(scroller);
		content.add(selectTheseRules);

        
		JPanel wrapper = new JPanel();
		wrapper.setPreferredSize(new Dimension(200, 300));
		wrapper.add(caption, BorderLayout.NORTH);
		wrapper.add(content, BorderLayout.SOUTH);

		return wrapper;
    }

    private JPanel createChooseMapPanel(){
        JPanel content = new JPanel();
        content.setBorder(BorderFactory.createEtchedBorder() );
        picPanel = new JPanel();
        
        // Layout Panels
        JPanel overallPanel = new JPanel();
        overallPanel.setLayout( new BorderLayout(2,20) );
        JPanel topPanel  = new JPanel();
        topPanel.setLayout( new BorderLayout() );
        topPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder()) );
        JPanel middlePanel = new JPanel();
        middlePanel.setLayout( new BorderLayout(0,5) );
        JPanel middleLeftPanel = new JPanel();
        middleLeftPanel.setLayout( new BorderLayout(0,2) );
        JPanel middleRightPanel = new JPanel();
        middleRightPanel.setLayout( new BorderLayout(0,5) );
        middleRightPanel.setPreferredSize( new Dimension (200,30) );
        JPanel bottomPanel = new JPanel();
        bottomPanel.setLayout( new BorderLayout(0,3) );
        
        // Labels
        
        String panelInfo = LanguagePack.getString("choose_map_message", DEFAULT_GROUP);
        
        JLabel topLabel = new JLabel(panelInfo);
        JLabel previewLabel = new JLabel(LanguagePack.getString("preview_map", DEFAULT_GROUP));
        JLabel dimensionLabel = new JLabel("Dimension: TODO");
        // TODO: real map dimensions
        JLabel mapListLabel = new JLabel(LanguagePack.getString("list_map", DEFAULT_GROUP));
        JLabel authorLabel = new JLabel(LanguagePack.getString("info_map", DEFAULT_GROUP));
        
        mapInfo = new JTextArea();
        
        
        JScrollPane scrollMapInfo = new JScrollPane(mapInfo);

        mapInfo.setBackground(Color.lightGray);
        mapInfo.setBorder( new javax.swing.border.EtchedBorder() );
        mapInfo.setFont( new Font("Tahoma", Font.PLAIN, 12) );
        mapInfo.setForeground(Color.BLACK);
        
        mapInfo.setColumns(20);
        mapInfo.setRows(4);
        
        mapInfo.setEditable(false);
        mapInfo.setWrapStyleWord(true);
        mapInfo.setLineWrap(true);
        
        FilenameFilter filter = new FilenameFilter () {
            public  boolean accept(File dir, String name) {
                if(name.endsWith(".xml"))
                    return true;
                return false;
            }
        };
        
        xmlMaps = new File(mapFolder).list(filter);
        
        for(int i=0; i<xmlMaps.length; i++){
            xmlMaps[i] = xmlMaps[i].substring(0, xmlMaps[i].length()-4);
        //    System.out.println(xmlMaps[i]);
        }
        
        
        mapImage = new CardImage("", "");
        //TODO : error
        updateMapPreview(xmlMaps[0]);
        picPanel.add(mapImage);
        mapList = new JList(xmlMaps);
        
        JScrollPane mapListScroller = new JScrollPane(mapList);
        mapList.setSelectedIndex(0);

        mapListScroller.setPreferredSize(new Dimension(174,207));

        
        JPanel scroll = new JPanel();

        scroll.setPreferredSize(new Dimension(268, 178));
        scroll.add(mapListScroller,BorderLayout.NORTH);
        
        // adding the layout Panels
        topPanel.add(topLabel, BorderLayout.WEST);
        
        middleLeftPanel.add(previewLabel, BorderLayout.NORTH);
        middleLeftPanel.add(picPanel, BorderLayout.CENTER);
        middleLeftPanel.add(dimensionLabel, BorderLayout.SOUTH);
        
        middleRightPanel.add(mapListLabel, BorderLayout.NORTH);
        middleRightPanel.add(scroll, BorderLayout.CENTER);
        
        middlePanel.add(middleLeftPanel, BorderLayout.WEST);
        middlePanel.add(middleRightPanel, BorderLayout.EAST);
        
        String fileName = xmlMaps[mapList.getSelectedIndex()] + "_info.txt";
        mapInfo.setText(getMapInfo(fileName) );
        
        
        bottomPanel.add(authorLabel, BorderLayout.NORTH);
        bottomPanel.add(scrollMapInfo, BorderLayout.CENTER);
        
        overallPanel.add(topPanel, BorderLayout.NORTH);
        overallPanel.add(middlePanel, BorderLayout.CENTER);
        overallPanel.add(bottomPanel, BorderLayout.SOUTH);
        
        overallPanel.repaint();
        content.add(overallPanel);
        
        
        
        
        mapList.addListSelectionListener( new ListSelectionListener(){
            public void valueChanged(ListSelectionEvent e){
                if(e.getValueIsAdjusting() == true)
                    return;
                mapName = xmlMaps[mapList.getSelectedIndex()];
                updateMapPreview(mapName);
                gameConfig.setBoardMap(mapName);
                
                replaceRoomCards(gameConfig, mapName);
                
                mapInfo.setText(getMapInfo(mapName + "_info.txt") );
            }
            
        }
        );
        
        return content;
    }
    
    /**
     * Replaces all room cards of the old map for those of the new one
     * 
     * @param gameConfig
     * @param mapName
     */
    synchronized private void replaceRoomCards(CluedoConfig gameConfig, String mapName) {
        CardCollection c = gameConfig.getCards();
        System.out.println(c.toXML());
        CardCollection toRemove = new CardCollection();
        
        for(int i =0;i< c.countCards();i++) {
            if(c.cardAt(i).getType().toLowerCase().equals("room"))
                toRemove.insertCard(c.cardAt(i));
        }
        for(int i=0;i<toRemove.countCards();i++)
            c.removeCard(toRemove.cardAt(i));
        
        try {
            StringTokenizer st = new StringTokenizer(Resources.catTextFileExt("Resources/Cards/" + mapName + ".cards",null));
            
            while(st.hasMoreElements() == true) {
                String next = st.nextToken();
                String []parts = next.split(",");
                if(parts.length == 2 && parts[0].charAt(0) != '#')
                    if(parts[1].toLowerCase().equals("room")) {
                        c.insertCard(new Card(parts[0], "Room"), 0);
                    }
                    
            }
            
        } catch (IOException e) {
//            e.printStackTrace();
            //System.out.println(""c.toXML());
        	
        	System.out.println("Where is : " + "Resources/Cards/" + mapName + ".cards ?");
        }
        

        
        
    }
    
    /**
     *This method will return the file info
     *on the given map name
     *  
     * @param fileName
     * @return
     * @throws IOException
     *
     */
    private String getMapInfo(String fileName) {
        String absolutePath = new File("./Resources/Maps/" + fileName).getAbsolutePath();
        StringBuffer info = new StringBuffer();
        
        try {  	
            BufferedReader mapInfoReader = new BufferedReader( new FileReader(absolutePath) );
            
            String line = "";
            while((line = mapInfoReader.readLine()) != null) {
                info.append(line + "\n");
            }
            
            mapInfoReader.close();
        }
        catch(Exception e ) {
            
        }
        
        return info.toString();
    }
    
    /**
     * Changes the map image preview, called from ItemChange event in list of maps.
     * 
     */
    private void updateMapPreview(String mapName) {
        String file = mapFolder + mapName + "_thumb.gif";
        mapImage.changeCard(file, mapName);
        mapImage.repaint();
    }
    
    public void actionPerformed(ActionEvent a) {
        
        if(a.getActionCommand().equals("start_game")) {
            int amount = 0;
            if(gameConfig.getPlayers() == null || gameConfig.getPlayers().size() == 0) 
                amount = 3;
            else
                amount = 3-gameConfig.getPlayers().size();
            
            if (gameConfig.getPlayers() == null || gameConfig.getPlayers().size() < 3) {
                JOptionPane.showMessageDialog(null,
                        addArguments(LanguagePack.getString("bad_amount_players", DEFAULT_GROUP), new String[] {""+amount}),
                        "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            else {
                
                String response = null;
                for(int i = 0; i < gameConfig.getPlayers().size(); i++)
                    System.out.println ( 
                            "[GConfig:] "+((Player)gameConfig.getPlayers().elementAt(i)).getRealName() + " playing as " +  ((Player)gameConfig.getPlayers().elementAt(i)).getCharacter() );
                setInterestingData(gameConfig);
            }
        }
        else {
            setInterestingData(null);
        }
        
        dispose();
    }
    
    /**
     * Used to generate JLabels with line-breaks or additional html, in a user-transparent way
     *
     */
    private String formatString(String data) {
        String output = data;
        
        output = output.replaceAll("\n", HTML_NEWLINE);
        output = HTML_ON + output + HTML_OFF;
        return output;
    }
    
    
    /**
     * Adds relevant arguments to string from String array 
     * 
     * @param string
     * @param names2
     * @return
     */
    private static String addArguments(String string, String[] names2) {
        for(int i=0;i<names2.length;i++)
            string = string.replaceAll("%"+(i+1), names2[i]);
        if(string.indexOf("@@") > -1) {
            string = addBreaks(string);
        }
        return string;
    }
    
    
    /**
     * @param string
     * @return
     */
    private static String addBreaks(String string) {
        string = string.replaceAll("@@", "<br>");
        string = Cluedo.API.Constants.HTML_ON + string + Cluedo.API.Constants.HTML_OFF;
        return string;
    }
    
}