"""Lets you spy on other players.

Copyright 2001 Cabochon Technologies, Inc.
Author:  Steve Yegge
"""

from java.lang import String
from wyvern.lib import Command, MethodHookCallback
from wyvern.kernel.maps import MapObject
from wyvern.world import World

class crystal_ball(MapObject, Command, MethodHookCallback):

    # sets class-default properties
    def initialize(self):
        self.super__initialize()

        self.setDefaultCategory('magic')
        self.setDefaultBitmap('crystal_ball')

        if not self.getProperty('short'):
            self.setProperty('short', 'crystal ball')

        if not self.getProperty('desc'):
            self.setProperty('desc', "Type 'view ' to use the ball.")

        if self.getIntProperty('value') == 0:
            self.setIntProperty('value', 10000)

        self.ensureWeight('5 lb')

    # wonder if we should worry about the conflict with ship 'view' command
    def knowsCommand(self, cmd):
        return String.startsWith(cmd, 'view')

    # Creates an event - finds the monster to suck in and records it
    # in a property on the event called 'target'.
    def createEvent(self, event):

        agent = event.getAgent()

        arg = event.getArgString()
        if not arg:
            return event.veto('View whom?')

        # figure out who
        if not String.equals(arg, 'off'):
            if not World.getPlayer(arg):
                return event.veto('That player is not online.')
            else:
                event.setProperty('player', arg)

        return event

    def execute(self, event):
        agent = event.getAgent()
        if event.isVetoed():
            agent.message(event.getFailureMessage())
            return 0

        # if 'view off', turn it off
        player = event.getProperty('player')
        if not player:
            return self.viewOff(agent)

        # no wiz snooping
        p = World.getPlayer(player)
        if p.hasProperty('wizard'):
            agent.message('You cannot view wizards with this ball.')
            return 0

        # if they're already viewing someone, handle specially
        old = agent.getProperty('@snooper')
        if old:
            if String.equals(old, player):
                agent.message('You are already viewing ' + player + '.')
                return 0
            else:
                # turn it off before switching to someone else
                self.viewOff(agent)

        return self.viewPlayer(agent, player)

    # take control of camera and position it on the other player
    def viewPlayer(self, agent, player):

        agent.controlCamera(0)
        target = World.getPlayer(player)
        ref = target.getReferenceLoc()
        map = target.getMap()
        cam = agent.getMapCamera()
        cam.setMap(map, ref.x, ref.y)

        # get on map hook - when they move, move the camera
        target.addMethodHook(self, 'add')

        # get on agent's move-hook as well, so if they move it's over
        agent.addMethodHook(self, 'add')

        # remember parameters for later
        self.target = target
        self.agent = agent
        self.camera = cam

        agent.setProperty("@snooper", player)
        agent.message('You begin viewing ' + target.getName() + '.')

    # stop viewing the target player
    def viewOff(self, agent):
        if not agent.hasProperty('@snooper'):
            agent.message('You are not using the crystal ball.')
            return

        self.target.removeMethodHook(self, 'add')
        self.agent.removeMethodHook(self, 'add')
        map = self.agent.getMap()
        ref = self.agent.getReferenceLoc()
        self.camera.setMap(map, ref.x, ref.y)
        self.agent.controlCamera(1)
        self.agent.removeProperty('@snooper')
        self.agent.message('You stop using the crystal ball.')

    # notification that the target (or agent) has moved
    def methodCalled(self, hookName, target, data):

        # if target moved, move the camera
        if target.equals(self.target):
            ref = target.getReferenceLoc()
            map = target.getMap()
            self.camera.setMap(map, ref.x, ref.y)

        # else stop
        self.viewOff(self.agent)

    def __repr__(self):
        return 'crystal ball'

    def toString(self):
        return self.__repr__()