#   Copyright (c) 2009 Axel Wachtler
#   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 authors 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.

# $Id: boardcfg.py,v 1.3 2009/11/14 17:54:01 awachtler Exp $

# === import ==================================================================
import ConfigParser
import sys, pprint, copy

pp = pprint.pprint

# === globals =================================================================
BOARDS = []
CFGP = None
# === functions ===============================================================

##
# read the board config file and return
# a list of sections
def get_boards(fname):
    global BOARDS
    BOARDS = read_config(fname)
    board_dict = generate_board_dictionary(BOARDS)
    return board_dict

##
#
def write_board_header_file(boards, fname):
    hfile = open(fname, "w")
    frag = "/* This file is autogenerated, do not edit, changes will be lost! */\n"\
            "#ifndef BOARD_CFG_H\n"\
            "#define BOARD_CFG_H (1)\n"

    frag += generate_include_fragment(boards)
    frag += "\n#endif /*BOARD_CFG_H*/\n"
    hfile.write(frag)
    hfile.close()

def show_boards(boards):
    if isinstance(boards, dict):
        bl = boards.values()
    else:
        bl = boards

    board_list = [(b.name, b) for b in bl]
    board_list.sort()
    tmp = ""
    for bn,b in board_list:
        nlist = [b.name]
        nlist.extend(getattr(b,'aliases','').split())
        tmp += "    "
        tmp += "|".join(nlist) + ":\n      "
        tmp += "%s\n" % getattr(b,'comment','-?-').replace("\n","\n      ")
    return tmp

##
# Read a config file and returns a list of BoardCfg instances.
#
# @param  fname win-ini style config file.
# @return list of BoardCfg instances
#
def read_config(fname):
    global CFGP
    ret = []
    cfgp = ConfigParser.ConfigParser()
    cfgp.read(fname)
    for brdname in cfgp.sections():
        brd = BoardCfg(brdname)
        for opt in cfgp.options(brdname):
            val = cfgp.get(brdname, opt)
            setattr(brd, opt, val)
        brd.postinit()
        ret.append(brd)
    CFGP = cfgp
    return ret

##
# Write a include file fragment.
#
# @param boards list of BoardCfg instances
#
def generate_include_fragment(boards):
    inclst = [ ]
    if isinstance(boards, dict):
        board_list = boards.values()
    else:
        board_list = boards
    board_list.sort()
    for b in board_list:
        nlist = [b.name]
        nlist.extend(getattr(b,'aliases','').split())
        tmp = " || ".join(["defined(%s)" % n for n in nlist]) + "\n"
        tmp += "# include \"%s\"\n" % (b.include)
        inclst.append(tmp)

    ret = '#if %s'\
          '#else\n'\
          '# error "BOARD_TYPE is not defined or wrong"\n'\
          '#endif\n' % \
            "#elif ".join(inclst)
    return ret


def generate_board_dictionary(boards):
    ret = {}
    for b in boards:
        if ret.has_key(b.name):
            print "duplicate board ID %s" % b.name
        else:
            ret[b.name] = b
    return ret


def generate_board_dictionary_expanded(boards):
    ret = {}
    for b in boards.values():
        board_names = [b.name]
        board_names.extend(getattr(b,'aliases','').split())
        for name in board_names:
            if ret.has_key(name):
                print "duplicate board ID %s" % name
                raw_input("press enter to continue")
            ret[name] = copy.copy(b)
            ret[name].name = name
            ret[name].aliases = ""
    return ret


# === classes =================================================================
class BoardCfg:
    def __init__(self,name):
        self.name = name

    def postinit(self):
        self.blstart = eval(self.bootoffset)
        self.F_CPU = self.f_cpu
        self.NO_APP = self.no_app.split()
        self.NO_XMPL = self.no_xmpl.split()
        me = getattr(self,'more_xmpls','')
        self.MORE_XMPLS = me.split()

    def get_ccopts(self):
        ccflags = "-D%s " % self.name
        ccflags += "-DF_CPU=%s " % self.f_cpu
        try:
            x = eval(self.ccflags)
            ccflags += x
        except:
            pass
        return ccflags

    def __str__(self):
        ret ="<%s>" % self.name

# === init ====================================================================

if __name__ == "__main__":
    for fname in sys.argv[1:]:
        bd = get_boards(fname)
        print "xxxx:",fname,bd
        print show_boards(bd)
