/***********************************************************************

GECCO, a platform for command and control gaming

Copyright (C) 2001 Henrik Bäärnhielm, Andreas Enblom, Niklas
Hallenfur, Karl Hasselström, Henrik Hägerström, Oskar Linde, Jing Fu
Zi and Jon Åslund

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.

***********************************************************************/

package gecco.client;
import gecco.client.*;

import java.awt.*;
import java.util.*;

/**
 *  This a test implementation of a server. It is very ugly and should only be
 *  used for testing purposes.
 *
 * @author     Andreas Enblom
 * @created    June 27, 2001
 */
public class TestServer implements Server {
    /**
     *  Description of the Field
     */
    long actionId = 0;
    /**
     *  Description of the Field
     */
    Client client;
    /**
     *  Description of the Field
     */
    final int numOfPieces = 100;
    /**
     *  Description of the Field
     */
    Position positions[] = new Position[numOfPieces];
    /**
     *  Description of the Field
     */
    boolean[] shouldRest = new boolean[numOfPieces];
    /**
     *  Description of the Field
     */
    Hashtable stateMap;
    /**
     *  Description of the Field
     */
    TestThread serverThread;
    /**
     *  Description of the Field
     */
    Dimension size = new Dimension(2000, 800);
    /**
     *  Description of the Field
     */
    Image map;


    /**
     *  Constructor for the TestServer object
     *
     * @param  c  Description of Parameter
     */
    public TestServer(Client c) {
        this.client = c;
        Game game = (Game) c;

        map = Toolkit.getDefaultToolkit().
                createImage("/afs/nada.kth.se/home/d98/d98-aen/Public/map.gif");
        MediaTracker tracker = new MediaTracker(game);
        tracker.addImage(map, 0);
        try {
            tracker.waitForAll();
        } catch (Exception ex) {
        }

        Image image = (new
                javax.swing.ImageIcon("/afs/nada.kth.se/home/d98/d98-aen/Public/type1.gif")).
                getImage();
        Symbols.addPieceSymbol("1", image);
        image = (new
                javax.swing.ImageIcon("/afs/nada.kth.se/home/d98/d98-aen/Public/type2.gif")).
                getImage();
        Symbols.addPieceSymbol("2", image);
        image = (new
                javax.swing.ImageIcon("/afs/nada.kth.se/home/d98/d98-aen/Public/type3.gif")).
                getImage();
        Symbols.addPieceSymbol("3", image);
    }


    /**
     *  Gets the AvailableRoles attribute of the TestServer object
     *
     * @return    The AvailableRoles value
     */
    public StringTokenizer getAvailableRoles() {
        String roles = "Red team leader,Red team commander,Red observer," +
                "Green team,Green observer,The eye of God";
        return (new StringTokenizer(roles, ","));
    }


    /**
     *  Gets the MapUpperLeft attribute of the TestServer object
     *
     * @return    The MapUpperLeft value
     */
    public Point getMapUpperLeft() {
        return new Point(0, 0);
    }


    /**
     *  Gets the MapSize attribute of the TestServer object
     *
     * @return    The MapSize value
     */
    public Dimension getMapSize() {
        return size;
    }


    /**
     *  Gets the Map attribute of the TestServer object
     *
     * @return    The Map value
     */
    public Image getMap() {
        return map;
    }


    /**
     *  Description of the Method
     *
     * @param  host  Description of Parameter
     * @param  port  Description of Parameter
     * @return       Description of the Returned Value
     */
    public boolean connect(String host, int port) {
        return true;
    }


    /**
     *  Description of the Method
     */
    public void disconnect() {
        if (serverThread != null) {
            serverThread.safeStop();
        }
    }


    /**
     *  Description of the Method
     *
     * @param  role  Description of Parameter
     * @return       Description of the Returned Value
     */
    public boolean joinAsRole(String role) {
        return true;
    }


    /**
     *  Description of the Method
     */
    public void startGame() {
        Vector actions = new Vector();
        actions.add(new Action("testpos", "Test action Position",
                Action.POSITION, false));
        actions.add(new Action("testpiece", "Test action Piece",
                Action.PIECE, false));
        actions.add(new Action("rest", "Rest", Action.VOID,
                true));
        actions.add(new Action("moveagain", "Move again", Action.VOID,
                true));

        for (int i = 0; i < numOfPieces; ++i) {
            Vector properties = new Vector();
            properties.add(new Property("Health", "" +
                    (int) Math.rint(Math.random() * 100) +
                    "%"));
            properties.add(new Property("Fuel", "" +
                    (int) Math.rint(Math.random() * 100) +
                    "%"));
            positions[i] = new Position(0, Math.random() * 700 + 50);
            client.addPiece(i, "Piece " + i, positions[i],
                    actions.elements(), properties.elements(),
                    "" + (int) Math.ceil(Math.random() * 3));
            shouldRest[i] = false;
        }

        serverThread = new TestThread();
        serverThread.start();
    }


    /**
     *  Description of the Method
     *
     * @param  pieceHandle  Description of Parameter
     * @param  a            Description of Parameter
     * @return              Description of the Returned Value
     */
    public long doAction(int pieceHandle, Action a) {
        ++actionId;
        if (a.getType().equals("rest")) {
            shouldRest[pieceHandle] = true;
        } else if (a.getType().equals("moveagain")) {
            shouldRest[pieceHandle] = false;
        } else if (a.getType().equals("testpos")) {
            Position p = (Position) a.getParameter();
            System.out.println("Action on position " + p.x + "," + p.y);
        } else if (a.getType().equals("testpiece")) {
            Piece p = (Piece) a.getParameter();
            System.out.println("Action on piece " + p.getHandle() +
                    " named " + p.getName());
        }
        client.actionReply(actionId - 1, true, "");
        return actionId;
    }


    /**
     *  Description of the Method
     *
     * @param  actionId  Description of Parameter
     */
    public void abortAction(long actionId) {
    }


    /**
     *  Description of the Class
     *
     * @author     d98-kha
     * @created    June 27, 2001
     */
    public class TestThread extends Thread {
        /**
         *  Description of the Field
         */
        boolean run = true;


        /**
         *  Description of the Method
         */
        public void safeStop() {
            run = false;
        }


        /**
         *  Main processing method for the TestThread object
         */
        public void run() {
            Point lastUpdatePoint = new Point(-1, 0);
            while (run) {
                try {
                    this.sleep(1000 / 24);
                } catch (Exception ex) {
                }
                if (!run) {
                    return;
                }
                for (int i = 0; i < 800; ++i) {
                    Point p = new Point(lastUpdatePoint.x + 1,
                            lastUpdatePoint.y + i);
                    client.invisibilizeMapPoint(p);
                }
                lastUpdatePoint.translate(1, 0);
                for (int i = 0; i < numOfPieces; ++i) {
                    if (shouldRest[i]) {
                        continue;
                    }
                    positions[i].translate(Math.random() * 4,
                            Math.random() * 2 - 1);
                    client.updatePiece(i, positions[i]);

                }
                /*
                 * if (lastUpdatePoint.x >= 100) {
                 * client.connectionLost();
                 * safeStop();
                 * }
                 */
            }
        }
    }
}
