# pygsear
# Copyright (C) 2003 Lee Harr
#
#
# This file is part of pygsear.
#
# pygsear 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.
#
# pygsear 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 pygsear; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


import sys

from pygame.locals import K_UP, K_DOWN, K_LEFT, K_RIGHT, K_LCTRL, K_LALT, K_RETURN

from pygsear.Network import reactor
from twisted.python import usage

from pygsear.Game import TwistedGame
from pygsear import Event, Drawable
from pygsear.locals import *

from Vehicles import LocalTank, RemoteTank, Drone
import Server, World

class TankGame(TwistedGame):
    splash_filename = 'tanks_logo.png'

    def __init__(self, reactor, host, port, solo):
        self.host = host
        self.port = port
        self.solo = solo
        TwistedGame.__init__(self, reactor=reactor)

    def initialize(self):
        self.set_background(color=DGREEN)

        if not self.solo:
            self.connection = Server.Connection(self)

        self.world = World.TankWorld()

        self.radar_echoes = []

        self.make_tank()
        self.set_active_screen(self.t1.active_screen)

        if self.solo:
            self.make_drone()
        else:
            self.make_enemy()

        self.sprites.draw = self.sprites.draw_visible

    def set_active_screen(self, screen):
        self.active_screen = screen
        self.world.set_active_screen(screen)

    def make_tank(self):
        if not hasattr(self, 't1'):
            self.t1 = LocalTank()
            self.t1.set_game(self)
            self.t1.center()
            self.sprites.add(self.t1)

            self.set_controls()

        else:
            self.sprites.add(self.t1)

    def make_drone(self):
        if not hasattr(self, 'his_tank'):
            self.his_tank = Drone()
            self.his_tank.set_game(self)
            self.sprites.add(self.his_tank)
            self.his_tank.shoot()

    def make_enemy(self):
        if not hasattr(self, 'his_tank'):
            self.his_tank = RemoteTank()
            self.his_tank.set_game(self)
            self.sprites.add(self.his_tank)

    def ping_radar(self, ev=None):
        self.clear_radar()
        echoes = self.world.where_is(self.t1.active_screen, self.his_tank.active_screen)
        if echoes:
            for echo in echoes:
                f = '%s.png' % echo
                im = Drawable.Image(filename=f)
                im.hidden = 0
                im.center()
                self.radar_echoes.append(im)
                self.sprites.add(im, level=0)
        else:
            f = 'same.png'
            im = Drawable.Image(filename=f)
            im.hidden = 0
            im.center()
            self.radar_echoes.append(im)
            self.sprites.add(im, level=0)

        self.reactor.callLater(1, self.clear_radar)

    def clear_radar(self):
        for echo in self.radar_echoes:
            echo.kill()
        self.radar_echoes = []

    def set_controls(self):
        if not hasattr(self, '_controls_set'):
            self._controls_set = 1
            self.events.add(Event.KEYDOWN_Event(key=K_UP, callback=self.t1.accelerate))
            self.events.add(Event.KEYUP_Event(key=K_UP, callback=self.t1.noaccelerate))
            self.events.add(Event.KEYDOWN_Event(key=K_DOWN, callback=self.t1.baccelerate))
            self.events.add(Event.KEYUP_Event(key=K_DOWN, callback=self.t1.nobaccelerate))

            self.events.add(Event.KEYDOWN_Event(key=K_RIGHT, callback=self.t1.right))
            self.events.add(Event.KEYUP_Event(key=K_RIGHT, callback=self.t1.noright))
            self.events.add(Event.KEYDOWN_Event(key=K_LEFT, callback=self.t1.left))
            self.events.add(Event.KEYUP_Event(key=K_LEFT, callback=self.t1.noleft))

            self.events.add(Event.KEYDOWN_Event(key=K_LCTRL, callback=self.t1.shoot))
            self.events.add(Event.KEYDOWN_Event(key=K_LALT, callback=self.t1.reload))

            self.events.add(Event.KEYDOWN_Event(key=K_RETURN, callback=self.ping_radar))

    def checkCollisions(self):
        shots = self.his_tank.collidelistall(self.t1.active_shots.sprites())
        for shot in shots:
            if shot.active_screen.name == self.his_tank.active_screen.name:
                shot.kill()
                self.his_tank.speed *= 0.5
                self.his_tank.hit()

        shots = self.t1.collidelistall(self.his_tank.active_shots.sprites())
        for shot in shots:
            shot.kill()
            if shot.active_screen.name == self.t1.active_screen.name:
                self.t1.speed *= 0.5
                if self.t1.to_kill == 1:
                    self.gameOver()
                self.t1.hit()

        for shot in self.his_tank.active_shots.sprites():
            if not shot.active_screen.name == self.t1.active_screen.name:
                shot.hidden = 1
            else:
                shot.hidden = 0
            if shot.collidelist(shot.active_screen.blocks.sprites()):
                shot.kill()
        for shot in self.t1.active_shots.sprites():
            if shot.collidelist(shot.active_screen.blocks.sprites()):
                shot.kill()

        if self.t1.active_screen.name == self.his_tank.active_screen.name:
            if self.t1.collide(self.his_tank):
                self.t1.speed = 0
                self.his_tank.speed = 0
                if self.his_tank.is_drone:
                    self.his_tank.switch()
                self.t1.solid(self.his_tank, move_both=1)

            if not self.t1.can_see(self.his_tank, self.world.blockrects):
                self.his_tank.hidden = 1
            else:
                self.his_tank.hidden = 0

        else:
            self.his_tank.hidden = 1

        block = self.his_tank.collidelist(self.his_tank.active_screen.blocks.sprites())
        if block:
            self.his_tank.solid(block)
            self.his_tank.stop()
            if self.his_tank.is_drone:
                self.his_tank.switch()
        else:
            if self.his_tank.is_drone:
                self.his_tank.noleft()

        block = self.t1.collidelist(self.t1.active_screen.blocks.sprites())
        if block:
            self.t1.solid(block)
            self.t1.speed = 0


class Options(usage.Options):
    optFlags = [
        ["solo", "s", "Solo game"],
    ]
    optParameters = [["host", "h", "localhost", "Server hostname / address"],
                        ["port", "p", "8778", "Server port"],
    ]


def main():
    config = Options()
    try:
        config.parseOptions() # When given no argument, parses sys.argv[1:]
    except usage.UsageError, errortext:
        print '%s: %s' % (sys.argv[0], errortext)
        print '%s: Try --help for usage details.' % (sys.argv[0])
        sys.exit(1)

    solo = config['solo']
    host = config['host']
    port = int(config['port'])

    g = TankGame(reactor=reactor, host=host, port=port, solo=solo)
    g.mainloop()
    reactor.run()


if __name__ == '__main__':
    main()
