from warnings import warn
from pathlib import Path

class Settings:
    """
    Settings manager
    """

    def version( self ):
        return '1.0.0'

    def __init__( self , arguments ):
        # Default configuration
        self.set_cache()
        self.set_input()
        self.set_inte_cal()
        self.set_no_cache()
        self.set_output()
        self.set_verbose()
        self.set_wave_cal()

        # configuration change
        if len( arguments ) < 1:
            raise Exception(
                'type \'' + __file__ + ' -h\' for more information'
            )

        index = 0
        while index < len( arguments ):
            argument = arguments[ index ]
            if argument[0] == '-':
                if len( argument ) < 2:
                    raise Exception(
                        'unknown argument, type \' + __file__ + \' -h' +
                        ' for more information'
                    )
                if argument[1] != '-':
                    if argument == '-h':
                        argument = '--help'
                    elif argument == '-V':
                        argument = '--version'
                    elif argument == '-v':
                        argument = '--verbose'
                    elif argument == '-n':
                        argument = '--no-cache'
                    elif argument == '-c':
                        if index == len( arguments ) - 1:
                            raise Exception(
                                'cache have to take a value'
                            )
                        arguments[ index + 1 ] = '--cache=' + \
                        arguments[ index + 1 ]
                        index += 1
                        continue
                    elif argument == '-o':
                        if index == len( arguments ) - 1:
                            raise Exception(
                                'output have to take a value'
                            )
                        arguments[ index + 1 ] = '--output=' + \
                        arguments[ index + 1 ]
                        index += 1
                        continue
                    elif argument == '-w':
                        if index == len( arguments ) - 1:
                            raise Exception(
                                'wavelength calibration have to take a value'
                            )
                        arguments[ index + 1 ] = '--wavelength=' + \
                        arguments[ index + 1 ]
                        index += 1
                        continue
                    elif argument == '-i':
                        if index == len( arguments ) - 1:
                            raise Exception(
                                'intensity calibration have to take a value'
                            )
                        arguments[ index + 1 ] = '--intensity=' + \
                        arguments[ index + 1 ]
                        index += 1
                        continue
                    else:
                        raise Exception(
                            'unknown argument "' + argument + \
                            '", type \'' + __file__ + \
                            ' -h\' for more information'
                        )
                if argument[1] == '-': # not elif because argument
                                       # can change in the last if
                    if argument == '--help':
                        print( self.help() )
                        exit()
                    elif argument == '--version':
                        print( self.version() )
                        exit()
                    elif argument == '--verbose':
                        self.set_verbose( True )
                    elif argument == '--no-cache':
                        self.set_no_cache( True )
                    elif (
                        len( argument ) > 8 and
                        argument[ : 8 ] == '--cache='
                    ):
                        self.set_cache( argument[ 8 : ] )
                    elif (
                        len( argument ) > 9 and
                        argument[ : 9 ] == '--output='
                    ):
                        self.set_output( argument[ 9 : ] )
                    elif (
                        len( argument ) > 13 and
                        argument[ : 13 ] == '--wavelength='
                    ):
                        self.set_wave_cal( argument[ 13 : ] )
                    elif (
                        len( argument ) > 12 and
                        argument[ : 12 ] == '--intensity='
                    ):
                        self.set_inte_cal( argument[ 12 : ] )
                    else:
                        raise Exception(
                            'unknown argument "' + argument + \
                            '", type \'' + __file__ + ' -h\' ' + \
                            'for more information'
                        )
            else:
                self.set_input( argument )
            index += 1

        if self.input == None:
            raise Exception( 'input should be given' )

    def set_cache( self , cache = None ):
        """
        Setter for cache (None or path)
        """
        if isinstance( cache , str ):
            self.cache = Path( cache )
        elif isinstance( cache , Path ):
            self.cache = cache
        elif cache == None:
            self.cache = cache
        else:
            raise TypeError(
                'cache should be a path'
            )
    def set_input( self , input = None ):
        """
        Setter for input file (None or path)
        """
        if isinstance( input , str ):
            self.input = Path( input )
        elif isinstance( input , Path ):
            self.input = input
        elif input == None:
            self.input = input
        else:
            raise TypeError(
                'input should be a path'
            )
        if self.input != None and not self.input.is_file():
            raise IOError(
                'could not open ' + str( self.input )
            )

    def set_inte_cal( self , intensity_calibration = None ):
        """
        Setter for intensity calibration (None or path)
        """
        if isinstance( intensity_calibration , str ):
            self.inte_cal = Path( intensity_calibration )
        elif isinstance( intensity_calibration , Path ):
            self.inte_cal = intensity_calibration
        elif intensity_calibration == None:
            self.inte_cal = intensity_calibration
        else:
            raise TypeError(
                'intensity calibration should be a path'
            )
        if self.inte_cal != None and not self.inte_cal.is_file():
            raise IOError(
                'could not open ' + str( self.inte_cal )
            )

    def set_no_cache( self , no_cache = False ):
        """
        Setter for no_cache (bool)
        """
        if isinstance( no_cache , bool ):
            self.no_cache = no_cache
        else:
            raise TypeError(
                'no_cache option should be a boolean'
            )

    def set_output( self , output = 'data.fits' ):
        """
        Setter for output (path)
        """
        if isinstance( output , str ):
            self.output = Path( output )
        elif isinstance( output , Path ):
            self.output = output
        else:
            raise TypeError(
                'output should be a path'
            )
        if self.output.is_file():
            warn(
                str( self.output ) + ' already exists, it will be ' +
                'overwritten',
                UserWarning  ,
            )

    def set_verbose( self , verbose = False ):
        """
        Setter for verbosity flag (bool)
        """
        if isinstance( verbose , bool ):
            self.verbose = verbose
        else:
            raise TypeError(
                'verbose should be a boolean'
            )

    def set_wave_cal( self , wavelength_calibration = None ):
        """
        Setter for wavelength calibration (None or path)
        """
        if isinstance( wavelength_calibration , str ):
            self.wave_cal = Path( wavelength_calibration )
        elif isinstance( wavelength_calibration , Path ):
            self.wave_cal = wavelength_calibration
        elif wavelength_calibration == None:
            self.wave_cal = wavelength_calibration
        else:
            raise TypeError(
                'wavelength calibration should be a path'
            )
        if self.wave_cal != None and not self.wave_cal.is_file():
            raise IOError(
                'could not open ' + str( self.wave_cal )
            )

    def help( self ):
        return '\
naroo_reader [options...] input\
\n    -w wavelength  wavelength calibration file, default to None.\
\n                   None means no wavelength interpolation\
\n    -i intensity   intensity calibration file, default to None.\
\n                   None means no intensity interpolation\
\n    -c --cache     use given cache file to store new temporary\
\n                   data or use old ones.\
\n    -h --help      show this help and quit\
\n    -n --no-cache  do not use already existing cache file.\
\n                   If cache is defined, the cache file will be\
\n                   overwrited.\
\n                   If cache is None, it does nothing\
\n    -o --output    Output file. Default to data.fits\
\n    -V --version   show version number and quit\
\n    -v --verbose   show more information to help debugging\
        '

    def __str__( self ):
        return '\
current settings:\
\n    cache:                  ' + str( self.cache ) + '\
\n    input:                  ' + str( self.input ) + '\
\n    intensity calibration:  ' + str( self.inte_cal ) + '\
\n    no cache flag:          ' + str( self.no_cache ) + '\
\n    output:                 ' + str( self.output ) + '\
\n    verbose flag:           ' + str( self.verbose ) + '\
\n    wavelength calibration: ' + str( self.wave_cal ) + '\
        '