# src/createPropertyClass.js

    import Shadow from "./Shadow";
    import StateType from "./StateType";

    /*
    	Factory function for creating an Property subclass suitable for using with new.

    	Parameters (all are optional):
    		shadowType: one of a pojo or a class. This parameter defines the new property's shadow
    			type. If pojo specified, each property and function is mapped onto a subclass of the
    			BaseShadowClass parameter. The BaseShadowClass parameter is ignored if this parameter
    			is a class.
    		stateType: a StateType instance defining the Property
    		specCallback: a callback function that will be passed the StateType spec for additional
    			customization, such as setting autoshadow, initial state, or readonly.
    		PropertyClass: the base class for defining the property. Must be a Property subclass.
    		BaseShadowClass: The base shadow class for when shadowType parameter is not a class/function
    			(default is Shadow)
    */
    export default function createPropertyClass(
    	shadowType,
    	initialState,
    	specCallback,
    	PropertyClass,
    	BaseShadowClass=Shadow)
    {
    	var ShadowClass;

    	// get the shadow class
    	if (typeof shadowType === 'function') {
    		// shadow class passed into method
    		ShadowClass = shadowType;
    	} else {
    		class CustomShadow extends BaseShadowClass { }

    		var proto = CustomShadow.prototype;
    		var names = Object.getOwnPropertyNames(shadowType);
    		var name, desc;

    		for (let i=0, len=names.length; i<len; i++) {
    			name = names[i];
    			desc = Object.getOwnPropertyDescriptor(shadowType, name);

    			Object.defineProperty(proto, name, desc);
    		}

    		ShadowClass = CustomShadow;
    	}

    	// create the property subclass
    	class CustomProperty extends PropertyClass {
    		constructor(stateType) {
    			super(stateType);

    			this.setShadowClass(ShadowClass);
    		}
    	}

    	// create the type class variable
    	StateType.defineType(CustomProperty, spec => {
    			if (initialState !== undefined) {
    				spec.initialState(initialState);
    			}

    			if (specCallback) {
    				specCallback(spec, CustomProperty);
    			}
    		});

    	return CustomProperty;
    }