"""
$URL: svn+ssh://svn.mems-exchange.org/repos/trunk/dulcinea/lib/material.py $
$Id: material.py 30544 2008-03-07 20:43:18Z dbinger $
"""
from dulcinea.category import Category
from durus.persistent import PersistentObject
from durus.persistent_dict import PersistentDict
from durus.persistent_list import PersistentList
from qp.lib.spec import boolean, sequence, instance, add_getters_and_setters
from qp.lib.spec import spec, specify, require, string, Specified, mapping
from qp.pub.common import get_publisher
from qpy import xml, xml_quote
from random import randrange


def get_material_db():
    return get_publisher().get_connection().get_root().get('material_db')

class Material (Category):
    """
    Represents a material and a category of materials.
    """
    html_name_is = spec(
        (string, None),
        "The name to be used in html displays. "
        "This may include html tags for subscripts. "
        "Other materials may have the same html_name, "
        "but that is probably a bad idea.")
    html_color_is = spec(
        (string, None),
        "A string in the form #ffee99 that identifies "
        "a color that might be used in html concerning "
        "this Material. "
        "Other materials may have the same color.")
    deleted_is = spec(
        boolean,
        "Tells if this this material is deprecated.")

    children_is = sequence(instance('Material'), PersistentList)
    parents_is = sequence(instance('Material'), PersistentList)

    def __init__(self, name, html_name=None, html_color=None):
        Category.__init__(self)
        specify(self,
                name=name,
                html_color=html_color or random_light_color(),
                html_name=html_name or name,
                deleted=0)

    def __str__(self):
        if self.get_children():
            return '%s (category)' % self.get_label()
        else:
            return self.get_label()

    def get_label(self):
        return self.label or self.name

    def format(self, html=False):
        if html:
            if self.html_name:
                return xml(self.html_name)
            else:
                return xml_quote(self.get_label())
        else:
            return self.get_label()

    def is_deleted(self):
        return self.deleted

    def is_other(self):
        return self.name == "other"

add_getters_and_setters(Material)

def random_light_color():
    red   = 256
    green = 256
    blue  = 256
    maximum_light = (256*3-100)
    minimum_light = 300
    while ((red+green+blue > maximum_light) or
           (red+green+blue < minimum_light)):
        red = randrange(16,256)
        green = randrange(16,256)
        blue = randrange(16,256)
    r = hex(red)[-2:]
    g = hex(green)[-2:]
    b = hex(blue)[-2:]
    return '#%s%s%s' % (r,g,b)

def material_sort(materials):
    """(seq [Material]) -> [Material]"""
    def lower_case_label(material):
        return material.get_label().lower()
    return sorted(materials, key=lower_case_label)


class MaterialDatabase (PersistentObject, Specified):

    materials_is = spec(
        mapping({string:Material}, PersistentDict),
        "all material objects keyed on name")

    def __init__(self):
        specify(self, materials=PersistentDict())

    def __getitem__(self, material_name):
        return self.materials[material_name]

    def add_material(self, material):
        require(material, Material)
        if self.materials.has_key(material.get_name()):
            raise ValueError(
                "material named '%s' already exists" % material.get_name())
        self.materials[material.get_name()] = material

    def get_material(self, material_name):
        return self.materials.get(material_name)

    def get_materials(self):
        return list(self.materials.values())

