#!/usr/bin/python

import os
import re
import platform
import string

# -----------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
# -----------------------------------------------------------------------

class PropertiesException(Exception):
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return repr(self.msg)

class Property:
    def __init__(self, k, v, c):
        self.k = k         # key
        self.v = v         # value
        self.c = c         # comments
        self.orig_v = v
    
    def reset(self):
        self.v = self.orig_v

    def __str__(self):
        return str(self.k) + '=' + str(self.v)

class Properties:
    def __init__(self):
        self.props = {}
        self.builtin = {}

        self.keys = []
        self.comments = []

        #
        # Create builtins corresponding to some of the java properties.
        #
        # We allow expansion on java system properties.  It's obviously not possible to
        # do most of them but these guys may have a use e.g. to put ducc_ling into
        # architecture-specific places.
        #
        (system, node, release, version, machine, processor) = platform.uname()
        if ( system == 'Darwin' ):
            self.builtin['os.arch'] = 'x86_64'
            self.builtin['os.name'] = 'Mac OS X'
        elif ( system == 'Linux' ):
            if ( machine == 'ppc64' ):
                self.builtin['os.arch'] = 'ppc64'
                self.builtin['os.name'] = 'Linux'
            elif ( machine == 'x86_64' ):
                self.builtin['os.arch'] = 'amd64'
                self.builtin['os.name'] = 'Linux'
            elif ( machine == 'ppc64le' ):
                self.builtin['os.arch'] = 'ppc64le'
                self.builtin['os.name'] = 'Linux'


    #
    # Expand all ${} values. The search order is:
    #    1 look in this properties file
    #    2 look in the environment
    #    3 look in a subset of the Java system properties (os.name & os.arch)
    #
    def do_subst(self, st):
        key = None
        p = re.compile("\\$\\{[a-zA-Z0-9_\\.\\-]+\\}")
        ndx = 0

        response = st.strip()
        m = p.search(response, ndx)    
        while ( m != None ):
            key = m.group()[2:-1]
            

            val = None
            if ( self.has_key(key) ):
                val = self.get(key)
            elif ( os.environ.has_key(key) ):
                val = os.environ[key]                
            elif (self.builtin.has_key(key) ):
                val = self.builtin[key]

            if ( val != None ):    
                response = string.replace(response, m.group() , val)
            ndx = m.start()+1
            m = p.search(response, ndx)
        
        return response

    def mkitem(self, line):
        #
        # First deal with line comments so we can preserve them on write
        # UIMA-5401 Don't allow '//' to start an embedded comment ... may be part of a value
        #
        if ( line.startswith('#') ):
            self.comments.append(line)
            return False

        if ( line == '' ):
            return False

        #
        # Now strip off embedded comments, these are lost, but they're not valid
        # for java props anyway.
        #
        ndx = line.find('#')   # remove comments - like the java DuccProperties
        if ( ndx >= 0 ):
            line = line[0:ndx]     # strip the comment
        line = line.strip()    # clear leading and trailing whitespace
        
        if ( line == '' ):
            return False

        mobj = re.search('[ =:]+', line)
        if ( mobj ):            
            key = line[:mobj.start()].strip()
            val = line[mobj.end():].strip()
            # print 'NEXT', mobj.start(), 'END', mobj.end(), 'KEY', key, 'VAL', val
            # val = self.do_subst(val)   # we'll do lazy subst on get instead
            self.props[key] = Property(key, val, self.comments)
            if ( key in self.keys ):
                self.keys.remove(key)
            self.keys.append(key)
            self.comments = []
        else:
            self.props[line] = Property(line, '', self.comments)
            self.keys.append(line)
            self.comments = []

    #
    # Load reads a properties file and adds it contents to the
    # hash.  It may be called several times; each call updates
    # the internal has, thus building it up.  The input file is
    # in the form of a java-like properties file.
    #
    def load(self, propsfile):
        if ( not os.path.exists(propsfile) ):
            raise PropertiesException(propsfile +  ' does not exist and cannot be loaded.')

        f = open(propsfile);
        for line in f:
            self.mkitem(line.strip())
        f.close()

    # read a jar manifest into a properties entity
    def load_from_manifest(self, jarfile):
        z = zipfile.ZipFile(jarfile)
        items = z.read('META-INF/MANIFEST.MF').split('\n')
        for item in items:
            self.mkitem(item)

    #
    # Try to load a properties file.  Just be silent if it doesn't exist.
    #
    def load_if_exists(self, propsfile):
        if ( os.path.exists(propsfile) ):
            return self.load(propsfile)
        
    #
    # Put something into the hash with an optional comment
    #
    def put(self, key, value, comment=[]):
        self.props[key] = Property(key, value, comment)
        self.keys.append(key)

    #
    # Put a Property object into the map
    #
    def put_property(self, p):
        self.props[p.k] = p
        self.keys.append(p.k)

    #
    # Get a value from the hash
    #
    def get(self, key):
        if ( self.props.has_key(key) ):
            return self.do_subst(self.props[key].v)   # we'll do lazy subst on get instead
        return None

    #
    # Get a Property object for manipulation (k, v, comment)
    #
    def get_property(self, key):
        if ( self.props.has_key(key) ):
            return self.props[key]                    # note no expansion.  
        return None

    #
    # Remove an item if it exists
    #
    def delete(self, key):
        if ( self.props.has_key(key) ):
            del self.props[key]
            self.keys.remove(key)
        
    #
    # make directories, if need be
    #
    def _makedirs(self, path):
        try:
            dir_path = os.path.dirpath(path)
            os.makedirs(dir_path)
        except:
            pass
        
    #
    # Write the has as a Java-like properties file
    #
    def write(self, propsfile):
        self._makedirs(propsfile)
        f = open(propsfile, 'w')
        for k in self.keys:
            p = self.props[k]
            v = p.v
            c = p.c
            for cc in c:
                f.write(cc + '\n')
            f.write(k + ' = ' + str(v) + '\n\n')

        f.close()

    #
    # return a shallow copy of the dictionary
    #
    def copy_dictionary(self):
        return self.props.copy()

    #
    # Return the entries (Property list) in the dictionary
    #
    def items(self):
        return self.props.items()

    #
    # The keys, in the order as defined in the input file
    #
    def get_keys(self):
        return self.keys

    #
    # check to see if the key exists in the dictionary
    #
    def has_key(self, key):
        return self.props.has_key(key)

    #
    # Return the length of the dictionary
    #
    def __len__(self):
        return len(self.props)
