package com.yourmajesty.models
{
    import flash.utils.describeType;
    import com.yourmajesty.debug.Console;
    
    /**
     * Extend this class to obtain automatic mapping of XML nodes to your model classes.
     * Attributes or child text nodes may be used interchangeably.
     * Colors and hexadecimal are parsed correctly if your field is of type int/uint and the 
     * datum is formatted like a hex number or hex color.
     * Arrays of strings are accepted as well.
     * If you wish, you may repurpose JSON code to interpret more values correctly.
     * 
     * If you use this class, please retain the following author tag:
     * @author Roger Braunstein | Your Majesty Co | 2007
     */
    public class AbstractXMLPopulatedModel
    {
        public function AbstractXMLPopulatedModel(xml:XML = null)
        {
            var xmlhash:Object = new Object();
            var variables:XMLList = describeType(this).variable;
            if (xml)
            {
                for each (var attribute:XML in xml.attributes())
                {
                    xmlhash[attribute.name().toString()] = attribute.toString();
                }
                for each (var child:XML in xml.children())
                {
                    xmlhash[child.name()] = child.text().toString();
                }
                
                for (var key:String in xmlhash)
                {
                    var varmatches:XMLList = variables.(@name == key);
                    var value:String = xmlhash[key];
                    if (varmatches && varmatches.length() == 1)
                    {
                        var type:String = varmatches[0].@type;
                        switch (type)
                        {
                            case "int":
                            case "uint":
                                var match:Object = (/^(0x|#)([a-fA-F0-9]+)/).exec(value);
                                if (match)
                                {
                                    this[key] = parseInt(match[2], 16);
                                } else {
                                    this[key] = parseInt(value);
                                }
                                break;
                                
                            case "Number":
                                this[key] = parseFloat(value);
                                break;
                                
                            case "String":
                                this[key] = value;
                                break;
                                
                            case "Array":
                                value = value.replace(/^\[/,"").replace(/\]$/,"");
                                this[key] = value.split(/\s*,\s*/);
                                break;
                                
                            /* case "Object"
                                //TODO: use JSON from Adobe corelib library if you want the bloat
                                break; */
                            
                            default:
                                Console.warn("The model couldn't interpret the value from XML into the requested type, " + type);
                                break;
                        }
                    }
                }
            }
        }
    }
}