import groovy.beans.Bindable
import groovy.swing.SwingBuilder
import java.awt.Color
import java.awt.Component
import java.awt.GridBagConstraints as GBC
import java.awt.GridBagLayout
import java.awt.BorderLayout
import javax.swing.AbstractListModel
import javax.swing.DefaultListModel
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.JList
import javax.swing.JOptionPane
import javax.swing.JPanel
import javax.swing.ListCellRenderer

public class TeamMaker {

    /* ======== MODEL ======== */

    public static def swing = new SwingBuilder()
    public static final String version = "0.2"
    public static final Random rand = new Random(System.currentTimeMillis())

    def frame
    def team1List
    def team2List
    def team1WinsButton
    def team2WinsButton
    def newGameButton
    def sittingList

    @Bindable boolean inGame = false
    @Bindable int teamSize = 4

    class Player implements Comparable<Player> {
        String name
        int gamesSat

        public int compareTo(Player that) {
            int r = this.gamesSat - that.gamesSat
            if (r == 0) r = this.name.compareTo(that.name)
            return r
        }
    }

    class SortedPlayerModel extends AbstractListModel {

    }


    /* ======== VIEW ======== */

        /*
           +--------------------------------------------------+
           | JDB TeamMaker v0.2                          _[]X |
           +--------------------------------------------------+
           |                                                  |
           | +-Current-Game--------------+ +-Sitting-Players+ |
           | |                           | |                | |
           | | Team 1          Team 2    | | Jeptha       3 | |
           | |   Derrick         Eric    | | Jack         2 | |
           | |   Shane           Brandon | | Sam          2 | |
           | |   Shane           Darren  | | Greg         2 | |
           | |   Christian       Brett   | | Frank        1 | |
           | +---------------------------+ | Chris D      1 | |
           |                               | Joshua       1 | |
           |                               |                | |
           |                               |                | |
           |                               |                | |
           |                               |                | |
           |                               |                | |
           |                               +----------------+ |
           +--------------------------------------------------+

         */

    private void init() {
        frame = swing.frame(title: "JDB TeamMaker v$version",
            size: [600, 400], locationRelativeTo: null,
            defaultCloseOperation: JFrame.EXIT_ON_CLOSE) {

            panel() {
                gridBagLayout()

                panel(constraints: gbc(gridx: 0, gridy: 0, fill: GBC.BOTH,
                        insets: [5, 5, 5, 0], weightx: 3, weighty: 1),
                    border: titledBorder(title: 'Current Game')) {
                    
                    gridBagLayout()

                    label('Team A', constraints: gbc(gridx: 0, gridy: 0,
                        fill: GBC.BOTH, insets: [5, 5, 0, 0]))

                    label('Team B', constraints: gbc(gridx: 1, gridy: 0, 
                        fill: GBC.BOTH, insets: [5, 5, 0, 5]))
                    
                    def teamListRenderer = new PlayerRenderer(showStats: false,
                        colored: false)

                    team1List = list(cellRenderer: teamListRenderer,
                        constraints: gbc(gridx: 0, gridy: 1, fill: GBC.BOTH,
                        insets: [5, 5, 0, 0], weightx: 2, weighty: 2),
                        model: new DefaultListModel())

                    team1WinsButton = button('Team A Wins',
                        constraints: gbc(gridx: 0, gridy: 2, anchor:
                            GBC.CENTER, insets: [5, 5, 5, 0]),
                        enabled: false,
                        actionPerformed: {
                            sittingList.model.each { it.gamesSat++ }
                            team1List.model.each { player ->
                                player.gamesSat = 0
                                sittingList.model.addElement(player)
                            }
                            team1List.model.clear()
                            team1List.repaint()
                            sittingList.repaint()
                            inGame = false
                            team1WinsButton.enabled = false
                            team2WinsButton.enabled = false
                        })

                    team2List = list(cellRenderer: teamListRenderer,
                        constraints: gbc(gridx: 1, gridy: 1, fill: GBC.BOTH,
                        insets: [5, 5, 0, 5], weightx: 2, weighty: 2),
                        model: new DefaultListModel())

                    team2WinsButton = button('Team B Wins',
                        constraints: gbc(gridx: 1, gridy: 2,
                            anchor: GBC.CENTER, insets: [5, 5, 5, 5]),
                        enabled: false,
                        actionPerformed: {
                            sittingList.model.each { it.gamesSat++ }
                            team2List.model.each { player ->
                                player.gamesSat = 0
                                sittingList.model.addElement(player)
                            }
                            team2List.model.clear()
                            team2List.repaint()
                            sittingList.repaint()
                            inGame = false
                            team1WinsButton.enabled = false
                            team2WinsButton.enabled = false
                        })

                }

                scrollPane(constraints: gbc(gridx: 1, gridy: 0, gridwidth: 2,
                        fill: GBC.BOTH, insets: [5, 5, 0, 5], weighty: 1),
                    border: titledBorder(title: 'Sitting Players')) {

                    sittingList = list(cellRenderer: new PlayerRenderer(
                            showStats: true, colored: true),
                            model: new DefaultListModel())
                }

                button('Next Game', constraints: gbc(gridx: 0, gridy: 1,
                    anchor: GBC.CENTER, insets: [5, 5, 5, 0]),
                    actionPerformed: { newGame() })

                button('Add Player', constraints: gbc(gridx: 1, gridy: 1,
                    anchor: GBC.CENTER, insets: [5, 5, 5, 0]),
                    actionPerformed: {
                        def name = JOptionPane.showInputDialog(frame,
                            "Enter the new player's name: ", "New Player...",
                            JOptionPane.QUESTION_MESSAGE)
                        def player = new Player()
                        player.name = name
                        player.gamesSat = 0
                        sittingList.model.addElement(player)
                    })

                newGameButton = button('Delete Player',
                    constraints: gbc(gridx: 2, gridy: 1, anchor: GBC.CENTER,
                        insets: [5, 5, 5, 5]),
                    actionPerformed: {
                        sittingList.model.removeElement(
                            sittingList.selectedValue) })

            }
        }

        swing.bind(source: this, sourceProperty: 'inGame',
            target: team1WinsButton, targetProperty: 'enabled')

        swing.bind(source: this, sourceProperty: 'inGame',
            target: team2WinsButton, targetProperty: 'enabled')

    }

    class PlayerRenderer extends JPanel implements ListCellRenderer {

        boolean showStats
        boolean colored

        private JLabel nameLabel
        private JLabel statsLabel
        private static def linedBorder
        private static def emptyBorder

        private def colors = [Color.getHSBColor(0.32f, 1f, 1f),
            Color.getHSBColor(0.24f,1f,1f), Color.getHSBColor(0.16f, 1f, 1f),
            Color.getHSBColor(0.08f, 1f, 1f), Color.getHSBColor(0.0f, 1f, 1f)]

        public PlayerRenderer(Map params) {
            showStats = params.showStats ?: false
            colored = params.colored ?: false

            setLayout(new BorderLayout())
            setOpaque(colored)

            linedBorder = TeamMaker.swing.lineBorder(color: Color.BLACK)
            emptyBorder = TeamMaker.swing.emptyBorder(1)

            nameLabel = TeamMaker.swing.label(opaque: false,
                horizontalAlignment: JLabel.LEADING)
            add(nameLabel, BorderLayout.WEST)

            if (showStats) {
                statsLabel = TeamMaker.swing.label(
                    horizontalAlignment: JLabel.TRAILING,
                    opaque: false)
                add(statsLabel, BorderLayout.EAST)
            }
        }

        public Component getListCellRendererComponent(JList list, Object value,
            int index, boolean isSelected, boolean cellHasFocus) {

            assert value instanceof Player

            nameLabel.setText(value.name)

            if (isSelected) setBorder(linedBorder)
            else setBorder(emptyBorder)
            
            if (showStats) 
                statsLabel.text = value.gamesSat

            if (colored) {
                def c = colors[Math.min(4, value.gamesSat)]
                setBackground(c)
            }

            return this
        }
    }
    

    /* ======== CONTROLLER ======== */

    public static void main(String[] args) {
        def inst = new TeamMaker()
        inst.frame.show()
    }

    TeamMaker() {
        init()
    }

    private void newGame() {
        if (team1List.model.size() < teamSize)
            populate(team1List, sittingList, teamSize)

        if (team2List.model.size() < teamSize)
            populate(team2List, sittingList, teamSize)

        team1WinsButton.enabled = true
        team2WinsButton.enabled = true
        newGameButton.enabled = false
    }

    private static void populate(def teamList, def sittingList, int teamSize) {
        while (teamList.model.size() < teamSize) {
            def player = choosePlayer(sittingList)
            teamList.model.addElement(player)
            sittingList.model.removeElement(player)
        }
    }

    private static Player choosePlayer(def list) {
        def choices = []
        list.model.each { choices << it }
        choices.sort { rand.nextInt() }
        return choices[0]
    }

    private float calculatePercentage(Player p, def sittingList) {

    }
}
