"""
A classic Horn of Plenty.  You can pull food out of it.

Copyright 2001 Cabochon Technologies, Inc.
Author:  Rhialto
"""

from java.lang import Exception

from wyvern.lib import Kernel, Range
from wyvern.lib.properties import Applyable
from wyvern.lib.classes import DynamicObject
from wyvern.common.util import Strings


class horn_of_plenty(DynamicObject, Applyable):
    """
    This is a Python documentation string.  You can put them
    just about anywhere, but it's most common to put them
    after a class or method declaration.

    The Horn of Plenty is an Applyable object that produces
    a random bit of food when you apply it.  It keeps track
    of its charges, so it doesn't last forever.
    """

    def initialize(self):
        """
        Sets default properties, in case someone forgot
        to set them in the archetype, or someone cloned the
        object directly without an archetype.

        The use of setDefault* and ensureWeight makes sure
        that the object only gets a copy of the property if
        it hasn't already inherited it from the archetype.
        This saves memory.
        """

        self.setDefaultImage('magic/misc/horn_of_plenty')
        self.setDefaultShortDesc('horn of plenty')
        self.setDefaultDesc('Apply the horn to get food from it.')
        self.ensureWeight('20 lb')

        self.initCharges()

        # it's usually best to call self.super__initialize() last.
        # Don't forget to call it, or your object may not work!
        self.super__initialize()


    def initCharges(self):
        """
        If we're not dead, and not charged yet, then we add
        an initial set of charges.  Then we set our shop value.
        """

        if (not self.hasProperty('dead')
            and not self.hasProperty('charged')):

            charge = Range.randomValue(100, 200)
            self.setIntProperty('charges', charge)
            self.setIntProperty('initial-charges', charge)
            self.addProperty('charged')

        self.setShopValue()


    def setShopValue(self):
        """Sets a shop value of 100 gp per charge."""

        charge = self.getIntProperty('charges')

        if self.getIntProperty('value') == 0:
            self.setIntProperty('value', charge*100)


    def apply(self, agent):
        """Creates some food, and uses a charge."""

        if self.hasProperty('dead'):
            agent.message("The Horn's magic is used up.")
            return

        self.useOneCharge()
        self.createFood(agent)


    def useOneCharge(self):
        """
        Uses up a charge.  If we're out, then we mark the
        item as dead, which prevents us from recharging it
        next time self.initialize() is called, e.g. when
        the player logs in again.
        """

        charge = self.getIntProperty('charges')
        charge = charge - 1

        self.setIntProperty('charges', charge)

        if charge == 0:
            self.addProperty('dead')


    def createFood(self, player):
        """
        Clones a random_food archetype.  If successful,
        we call a utility method below to add it to their inv.
        If it fails, we print an error message to the player.
        If the player is a Wizard, we show very detailed error info.
        """

        try:
            random = Kernel.instantiate('random/random_food')
            food = random.generate()
            self.addFoodToInventory(player, food)

        except Exception, x:

            player.message('An error occurred - please report a bug.')

            # show wizards the error, for debugging.  We use
            # the wyvern.common.util.Strings class to print out
            # a stack trace for the object, to send as a message

            if player.isWizard():
                player.message(Strings.captureStackTrace(x))


    def addFoodToInventory(self, player, food):
        """
        Tries to put the food in the player's inventory; if that fails,
        it puts the food on the ground where the player is standing,
        using food.positionAt(player)
        """

        # don't let people sell the food for money
        food.setIntProperty('value', 0)

        player.message('You pull some food out of the horn.')

        try:
            inv = player.inventory
            inv.add(food)
        except:
            player.message('The food falls on the ground.')
            food.positionAt(player)