# Copyright (c) 2016 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2008-2009 The Hewlett-Packard Development Company
# Copyright (c) 2004-2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Nathan Binkert

from __future__ import print_function

import os
import re
import sys

import convert
import jobfile

from attrdict import attrdict, multiattrdict, optiondict
from code_formatter import code_formatter
from multidict import multidict
from orderdict import orderdict
from smartdict import SmartDict
from sorteddict import SortedDict

# panic() should be called when something happens that should never
# ever happen regardless of what the user does (i.e., an acutal m5
# bug).
def panic(fmt, *args):
    print('panic:', fmt % args, file=sys.stderr)
    sys.exit(1)

# fatal() should be called when the simulation cannot continue due to
# some condition that is the user's fault (bad configuration, invalid
# arguments, etc.) and not a simulator bug.
def fatal(fmt, *args):
    print('fatal:', fmt % args, file=sys.stderr)
    sys.exit(1)

# warn() should be called when the user should be warned about some condition
# that may or may not be the user's fault, but that they should be made aware
# of as it may affect the simulation or results.
def warn(fmt, *args):
    print('warn:', fmt % args, file=sys.stderr)

# inform() should be called when the user should be informed about some
# condition that they may be interested in.
def inform(fmt, *args):
    print('info:', fmt % args, file=sys.stdout)

class Singleton(type):
    def __call__(cls, *args, **kwargs):
        if hasattr(cls, '_instance'):
            return cls._instance

        cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instance

def addToPath(path):
    """Prepend given directory to system module search path.  We may not
    need this anymore if we can structure our config library more like a
    Python package."""

    # if it's a relative path and we know what directory the current
    # python script is in, make the path relative to that directory.
    if not os.path.isabs(path) and sys.path[0]:
        path = os.path.join(sys.path[0], path)
    path = os.path.realpath(path)
    # sys.path[0] should always refer to the current script's directory,
    # so place the new dir right after that.
    sys.path.insert(1, path)

# Apply method to object.
# applyMethod(obj, 'meth', <args>) is equivalent to obj.meth(<args>)
def applyMethod(obj, meth, *args, **kwargs):
    return getattr(obj, meth)(*args, **kwargs)

# If the first argument is an (non-sequence) object, apply the named
# method with the given arguments.  If the first argument is a
# sequence, apply the method to each element of the sequence (a la
# 'map').
def applyOrMap(objOrSeq, meth, *args, **kwargs):
    if not isinstance(objOrSeq, (list, tuple)):
        return applyMethod(objOrSeq, meth, *args, **kwargs)
    else:
        return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq]

def compareVersions(v1, v2):
    """helper function: compare arrays or strings of version numbers.
    E.g., compare_version((1,3,25), (1,4,1)')
    returns -1, 0, 1 if v1 is <, ==, > v2
    """
    def make_version_list(v):
        if isinstance(v, (list,tuple)):
            return v
        elif isinstance(v, str):
            return map(lambda x: int(re.match('\d+', x).group()), v.split('.'))
        else:
            raise TypeError()

    v1 = make_version_list(v1)
    v2 = make_version_list(v2)
    # Compare corresponding elements of lists
    for n1,n2 in zip(v1, v2):
        if n1 < n2: return -1
        if n1 > n2: return  1
    # all corresponding values are equal... see if one has extra values
    if len(v1) < len(v2): return -1
    if len(v1) > len(v2): return  1
    return 0

def crossproduct(items):
    if len(items) == 1:
        for i in items[0]:
            yield (i,)
    else:
        for i in items[0]:
            for j in crossproduct(items[1:]):
                yield (i,) + j

def flatten(items):
    while items:
        item = items.pop(0)
        if isinstance(item, (list, tuple)):
            items[0:0] = item
        else:
            yield item

# force scalars to one-element lists for uniformity
def makeList(objOrList):
    if isinstance(objOrList, list):
        return objOrList
    return [objOrList]

def printList(items, indent=4):
    line = ' ' * indent
    for i,item in enumerate(items):
        if len(line) + len(item) > 76:
            print(line)
            line = ' ' * indent

        if i < len(items) - 1:
            line += '%s, ' % item
        else:
            line += item
            print(line)

def readCommand(cmd, **kwargs):
    """run the command cmd, read the results and return them
    this is sorta like `cmd` in shell"""
    from subprocess import Popen, PIPE, STDOUT

    if isinstance(cmd, str):
        cmd = cmd.split()

    no_exception = 'exception' in kwargs
    exception = kwargs.pop('exception', None)

    kwargs.setdefault('shell', False)
    kwargs.setdefault('stdout', PIPE)
    kwargs.setdefault('stderr', STDOUT)
    kwargs.setdefault('close_fds', True)
    try:
        subp = Popen(cmd, **kwargs)
    except Exception as e:
        if no_exception:
            return exception
        raise

    return subp.communicate()[0]

def makeDir(path):
    """Make a directory if it doesn't exist.  If the path does exist,
    ensure that it is a directory"""
    if os.path.exists(path):
        if not os.path.isdir(path):
            raise AttributeError("%s exists but is not directory" % path)
    else:
        os.mkdir(path)

def isInteractive():
    """Check if the simulator is run interactively or in a batch environment"""

    return sys.__stdin__.isatty()
