# -*- coding: UTF-8 -*-
#    This file is part of arena.
#   
#    arena 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.
#
#    arena is distributed in the hope that it will be useful, but
#    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABLITY
#    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 arena.  If not, see <http://www.gnu.org/licenses/>. 

## @file
#  This file defines a base application class, which is responsible for driving
#  the operations of the overall script.

from Library.Base.Classwork import AnObject
from Library.String.Utilities import IsPrintable 
import os, os.path, sys

## The format used to construct a string representation of AnApplication for
#  debugging and status output.
aStringRepresentation = "{appname} {appversion}"
## The default path viewpoint returned by the path() method
aDefaultPathViewpoint = "local"

## The base application class.  This class defines some methods that it
#  does not implement, and so it should never be instantiated directly.
class AnApplication(AnObject, IsPrintable):
    ## Construct a new instance of the application.
    #
    #  Any arguments passed in \p arguments are stored internally.
    def __init__(Self, **arguments):
        AnObject.__init__(Self)
        # Append the provided arguments to any that are pre-programmed into
        # the class
        if len(arguments) > 0:
            Self._options.update(arguments)
    
    ## Initializer    
    def init(Self):
        result = AnObject.init(Self)
        
        if result == True:
            Self._options = {}
            Self._name = Self.displayName()
            Self._version = "v1.0"
            # The path to the executing script
            Self._path = {
              "local": os.path.dirname(sys.argv[0])
            }
            
            # Correct for missing paths or directory placeholders (".", "..")
            if len(Self._path["local"]) == 0:
                Self._path["local"] = os.getcwd()
                
            elif Self._path["local"][0] == ".":
                Self._path["local"] = \
                  os.path.abspath(Self._path["local"])
                  
            ## The name of the executing script
            Self._script = os.path.basename(sys.argv[0])
            
        return result
        
    ## Destructor
    def __del__(Self):
        AnObject.__del__(Self)
        
    ## Run the application.
    #    
    #  This is the main loop of the application.  It is expected to return
    #  a code to indicate success (0) or failure (non-zero).  In the default
    #  implementation of AnApplication, it always returns zero.  This routine
    #  must be overridden by descendant classes that are intended to do 
    #  anything useful. """
    def run(Self):
        return 0
        
    # IsPrintable implementation -----------------------------------------------
    ## Construct a string representation of the application (the name
    #  and version string).
    #    
    #  The representation is formatted based on the string provided by 
    #  #aStringRepresentation.
    def toString(Self):
        return aStringRepresentation.format(appname=Self._name,
          appversion=Self._version)
          
    # Properties ---------------------------------------------------------------
    ## Retrieves the value of the named option.
    #    
    #  This value is retrieved from the dictionary of application options,
    #  which includes those specified at the time the application instance was
    #  created.
    def option(Self, optionName):
        if optionName in Self._options:
            return Self._options[optionName]
            
        return None
        
    ## Retrieve the version string for the application. 
    #    
    #  This value is retrieved from the internal "version" attribute, which is
    #  set by the class on initialization.
    def version(Self):
        return Self._version
        
    ## Retrieve the path to the running script, either for local use or the
    #  use of the remote client.
    #
    #  `viewpoint` specifies whether the routine should return the path as
    #  seen by the system (i.e., `/home/username/public/file`) or as seen by
    #  the client (i.e., `/public/file`).  
    #
    #  The optional `appendix` argument may specify a path or file name that
    #  should be included in the returned result; if this parameter is omitted,
    #  the function simply returns the path to the running script.
    def path(Self, viewpoint=aDefaultPathViewpoint, appendix=None):
        result = Self._path[viewpoint]
        
        if appendix is not None:
            appendix = str(appendix)
            
            # If the appendix does not represent an absolute path, make it one
            if (len(appendix) > 0) and (appendix[0] != "/"):
                result += "/" + appendix
                
            else:
                result = appendix
            
        return result
    
    ## Retrieve the name of the executing script.  
    def script(Self):
        return Self._script
