'''
    A simple dunnet-style text adventure
    Copyright (C) 2013  Matthew Oztalay

    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 3 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, see <http://www.gnu.org/licenses/>.
'''

from game.globals import item
import game.locations

# define specific items that need additional code for interaction
class stasisPod ( item ) :
    '''
        Item with functionality relating to stasis pods
    '''
    def __init__(self,name):
        item.__init__(self, name, False)
        
        self.interactDict['eject'] = self.eject
        self.interactDict['occupy'] = self.occupy
        self.ejectText = 'The pod clanks and clunks back on a track and exits the room through a hole in the floor. The beacon should have activated. Someone will probably come to pick it up... eventually.'
        self.occupyText = 'Yanking the door open, you rip the occupant out of the padded interior of the sleep pod. As you close the lid in front of you, you see the occupant convulsing on the floor. Machinery rattles, a pop, then the hum of the ship\'s core fades away.\n\nIs that someone knocking?' 
        
    def eject ( self, *args ) :
        print(game.utilities.wordWrap(self.ejectText))
        if self.name in game.locations['stasis'].items:
            del game.locations['stasis'].items[game.locations['stasis'].items.index(self.name)]
        
    def occupy (self, *args):
        return 'stasis'
        
class engineCore ( item ):
    '''
        Engine core class, modifies epilogue
    '''
    def __init__(self):
        item.__init__(self, 'core', False)
        
        self.interactDict['eject'] = self.eject
        
        self.ejectText = 'A manual lever releases the core from its bindings and opens a door to space. A track moves the core out the door, and fires retro-rockets. After a short moment, the ship jostles a bit, then silence.'
        
    def eject(self, *args):
        print(game.utilities.wordWrap(self.ejectText))
        if 'core' in game.locations['engineering'].items:
            del game.locations['engineering'].items[game.locations['engineering'].items.index('core')]
    
class fusebox ( item ) :
    '''
    '''
    def __init__(self):
        item.__init__(self, 'fusebox', False)
        
        self.desc = 'How long had it been since that power coupler had been replaced?'
        self.locationDesc = 'Smoke and sparks spew forth from the nearby fusebox.'
        self.interactDict['repair'] = self.repair
        
    def repair(self, *args):
        if 'coupler' in game.inventory:
            self.locationDesc = 'The fusebox is quiet now.'
            self.desc = 'Really need to spend more time maintaining the ship... if you ever get out of this.'    
        game.locations['elevator'].repair()
    
class display ( item ) :
    '''
        A specific item with which the player can interact,
        which requires additional functionality on top of 
        the base functionality of an item.
    '''
    def __init__(self):
        item.__init__(self, 'display', False)
        self.locationDesc = 'One lone display remains lit.'
        self.desc = 'It wants you to type a password into it before it will do anything'
        
        self.exitVar = False
        
        self.locked = True
        self.password = '12345'
        self.loginAttempts = 0
        self.loginMax = 3
        
        self.verbs = {'exit':['logoff','exit','quit'],
                      'help':['help','?'],
                      'status':['status'],
                      'login':['login','password'],
                      'eject':['eject']}
        
        self.typeDict = {'exit': self.exit,
                         'help': self.help,
                         'login':  self.login,
                         'status': self.status,
                         'eject': self.eject}
        
        self.interactDict['type'] = self.type
        self.interactDict['use'] = self.type
        
        self.strings = self.setStrings()
        
    def setStrings(self):
        '''
            Returns the dict of strings used by the display for user interaction.
            Called after every interaction to ensure the core and sleep pods statuses are
            properly updated.
        '''
        return {'locked':'Command unavailable while terminal is locked.',
                        'exit':'Logging off...',
                        'help':'''
ShipOS v2.30 (C) ShipTek Industries

help                 Displays this string
login <password>     Attempts to login using the input password. If invalid password, fails.
exit                 Ends the current sessions
eject <objectName>   Trigger the ejection process for the given object
status <subsystem>   Outputs the status of the input subsystem
status ship          
status help
''',
                        'statusHelp':'''
status shields       Output status of shields
status engines       Output status of engines
status power         Output status of power
status life          Output status of life
status weapons       Output status of weapons
status pods          Output status of sleep pods
status comms         Output status of communication systems
status core          Output status of the engine core
''',
                        'statusShields':'Shield Integrity = 0.00%',
                        'statusEngines':'Engine Fuel = 0 units\nEngine Output Capacity 0.00%\n\n** WARNING **\nPossible coolant leak detected\nEvacuate Immediately\n',
                        'statusPower':'Reactor Fuel = 0 units\n',
                        'statusLife':'Life Support\nCO2 Cycler Output = 10%O2 Available Time = 56:23',
                        'statusWeapons':'Point Defense Turrets = Offline\nForward Laser = Unresponsive\nTorpedo Launcher = Unresponsive\n',
                        'statusPods':'Sleep Pods\nTotal Pods = {0}\nOccupied Pods = {0}\nStable Pods = {0}\n\n{1}'.format(len(game.locations['stasis'].items), self.makeStasisString()),
                        'statusComms':'Comm Array Offline',
                        'statusShip':'Ship Status Overview\nEngine offline, possibly critical\nEvacuation Recommended',
                        'statusCore':'{0}'.format(self.getCoreStatus()),
                        'statusInvalid':'Invalid subsystem.',
                        'pwdInvalid':'Password Invalid. Please try again.',
                        'pwdSuccess':'Login successful, system unlocked.'
                        }
        
    def getCoreStatus(self):
        if 'core' in game.locations['engineering'].items:
            return 'Containment failure imminent. Recommend eject.'
        else:
            return 'Core missing.'
        
    def makeStasisString (self):
        string = ''
        for item in game.locations['stasis'].items:
            string += item + '\n'
        return string
        
    def eject (self, *args ) :
        if args:
            locations = ['engineering', 'stasis']
            ejectItem = args[0][0].lower()
            found = False
            for loc in locations:
                if ejectItem in game.locations[loc].items:
                    del game.locations[loc].items[game.locations[loc].items.index(ejectItem)]
                    found = True
                    print('Ejected.')
            if not found:
                print('Object not found.')
        else:
            print('INVALID OPTION')  
        
    def status (self, *args ) :
        '''
            Handles actions to occur with the status command
        '''
        if args:
            args = args[0]
            if not self.locked:
                if args[0] == 'help':
                    print(self.strings['statusHelp'])
                elif args[0] == 'shields':
                    print(self.strings['statusShields'])
                elif args[0] == 'engines':
                    print(self.strings['statusEngines'])
                elif args[0] == 'power':
                    print(self.strings['statusPower'])
                elif args[0] == 'life':
                    print(self.strings['statusLife'])
                elif args[0] == 'weapons':
                    print(self.strings['statusWeapons'])
                elif args[0] == 'pods':
                    print(self.strings['statusPods'])
                elif args[0] == 'comms':
                    print(self.strings['statusComms'])
                elif args[0] == 'ship':
                    print(self.strings['statusShip'])
                elif args[0] == 'core':
                    print(self.strings['statusCore'])
                else:
                    print(self.strings['statusInvalid'])
            else:
                print(self.strings['locked'])
        else:
            print(self.strings['statusInvalid'])
            
    def exit (self, *args ) :
        '''
            Flips the exit variable to get the player out of the loop
        '''
        print('Goodbye.')
        self.exitVar = True

    def help (self, *args ) :
        print(self.strings['help'])
        
    def login (self, *args ) :
        args = args[0]
        if args[0] == self.password:
            print(self.strings['pwdSuccess'])
            self.locked = False
        else:
            print(self.strings['pwdInvalid'])
            self.loginAttempts += 1
            
        if self.loginAttempts >= self.loginMax:
            self.exit()
        
    def type (self, *args ) :
        '''
            Starts a new loop similar to the main game's logic, but
            with less options. More hardcoded.
        '''
        print('System mainframe error. Admin override required to access.')
        self.exitVar = False
        while not self.exitVar:
            typed = input('>>>').lower()
            tokens = typed.split(' ')
            foundVerb = False
            for verb in self.verbs:
                if tokens[0] in self.verbs[verb]:
                    foundVerb = verb
                
            if foundVerb:
                self.typeDict[foundVerb](tokens[1:])
                
            else:
                print('INVALID INPUT')
            
            # update the strings for ship status
            self.strings = self.setStrings()

# set up all the items in the game.
itemDict = {'porthole':item('porthole', False),
         'box':item('box', False),
         'coupler':item('coupler', True),
         'papers':item('papers', True),
         'notebook':item('notebook', True),
         'display':display(),
         'poda':stasisPod('poda'),
         'podb':stasisPod('podb'),
         'podc':stasisPod('podc'),
         'podd':stasisPod('podd'),
         'core':engineCore(),
         'fusebox':fusebox()
         }

itemDict['porthole'].desc = 'Looking out, you see debris floating about the ship. An asteroid lazily rolls away from the ship off in the distance.'
itemDict['porthole'].locationDesc = 'A small porthole permits viewing of that which is not contained by the hull.'
itemDict['porthole'].grabText = itemDict['porthole'].hitText = itemDict['porthole'].pokeText = 'That\'s not a good idea.'

itemDict['papers'].desc = 'Technical specs, blueprints, manifests. Some are charred, others bloodied.'
itemDict['papers'].locationDesc = 'Papers strewn across the floor.'
#itemDict['papers'].grabText = 'There\'s no time for that.'
itemDict['papers'].hitText = 'Why would you do such a thing?'
itemDict['papers'].pokeText = 'The papers are shuffled by your advances.'

itemDict['box'].desc = 'It looks like someone was trying to repair the toilet, but took the tools. The only thing left is a power coupler.'
itemDict['box'].locationDesc = 'A small box sits on the floor in a puddle.'

itemDict['coupler'].desc = 'Regulates the flow of power from Point A to Point B. This one looks to be in remarkably good shape, all things considered.'
itemDict['coupler'].locationDesc = 'You see the glint of a power coupler.'

itemDict['notebook'].desc = 'It looks like the captain\'s log. The latest entry reads: "I hope someone finds this. Antenna is too badly damaged to get a message out. Computers are trashed. If anyone wants to try, password is 12345.\nI\'m so sorry."'
itemDict['notebook'].locationDesc = 'A red notebook sits open atop the solitary desk in the room. '

itemDict['poda'].desc = 'Someone important resides within. Power is on, vitals look good.'
itemDict['poda'].locationDesc = 'PodA shows green.'

itemDict['podb'].desc = 'Someone important resides within. Power is on, vitals look good.'
itemDict['podb'].locationDesc = 'PodB shows green.'

itemDict['podc'].desc = 'Someone important resides within. Power is on, vitals look good.'
itemDict['podc'].locationDesc = 'PodC shows green.'

itemDict['podd'].desc = 'Someone important resides within. Power is on, vitals look good.'
itemDict['podd'].locationDesc = 'PodD shows green.'

itemDict['core'].desc = 'A powerful, light-emitting beast. It looks like it took a few hits, and could breach containment at any moment, destroying the ship and killing everyone aboard.'
itemDict['core'].locationDesc = 'The ship\'s core sputters with some remaining life.'