TryGetValueOption = {
    Normal:0,
    Trim:1,
    Boolean:2,
    Integer:3,
    Float:4
};
CursorTypes = {
    Default:0,
    Crosshair:1,
    Help:2,
    Move:3,
    NoDrop:4,
    NotAllowed:5,
    Pointer:6,
    Progress:7,
    Text:8,
    Wait:9
};
AuthorAlignment = {
    TopLeft:0,
    MiddleLeft:1,
    BottomLeft:2,
    TopRight:3,
    MiddleRight:4,
    BottomRight:5,
    TopCenter:6,
    MiddleCenter:7,
    BottomCenter:8
};
BorderTypes = {
    Solid:0,
    DoubleBorder:1,
    Dotted:2,
    Dashed:3,
    Inset:4,
    Outset:5,
    Ridge:6,
    Groove:7,
    Hidden:8
};
BackgroundStyles = {
    Transparent:0,
    Solid:1,
    LinearGradient:3,
    RadialGradient:4
};
BackgroundShapes = {
    Rectangle:0,
    RoundedCornerRectangle:1,
    Eclipse:2,
    Octagon:3,
    TriangleRight:6,
    TriangleUp:7,
    TriangleLeft:8,
    TriangleDown:9,
    Diamond:10,
    Hexagon:12
};
AuthorEffects = {
    NoEffect:0,
    SlideUp:1,
    SlideDown:2,
    ZoomOut:3,
    SlideLeft:4,
    SlideRight:5,
    SlideTLBR:6,
    SlideTRBL:7,
    SlideBLTR:8,
    SlideBRTL:9,
    FadeIn:10,
    Highlight:11
};
Easings = {
    Linear: 0,
    BackIn: 1,
    BackOut: 2,
    BounceIn: 3,
    BounceOut: 4,
    Ease: 5,
    EaseIn: 6,
    EaseOut: 7,
    EaseInOut: 8,
    ElasticIn: 9,
    ElasticOut: 10
};
NavigationTypes = {
    Next:0,
    Back:1,
    Skip:2,
    ToPreviousMenu:3,
    ToMainMenu:4,
    ToResponse:5,
    Exit:6,
    Repeat:7,
    AudioOnOff:8,
    SynchOnOff:9
};
ButtonFunctions = {
    NormalButton:1,
    NavigationButton:2,
    MenuButton:3
};
ButtonTextPosition = {
    Left:3,
    Right:4,
    Top:2,
    Bottom:1,
    Over:0
};
function disableSelection() {
    try {
        var obj = Ext.get(event.srcElement.id);
        event.returnValue = obj.dom.tagName == "INPUT" || obj.dom.tagName == "TEXTAREA";
    }
    catch (err) {
        event.returnValue = false;
    }
}

XmlHelper = {
    getStringAttribute:function (xmlNode, attr, t) {
        var rawValue = xmlNode.getAttribute(attr);
        if (t) {
            rawValue = Ext.String.trim(rawValue.toString());
        }
        return rawValue;
    },
    getIntegerAttribute:function (xmlNode, attr) {
        return parseInt(xmlNode.getAttribute(attr));
    },
    getFloatAttribute:function (xmlNode, attr) {
        return parseFloat(xmlNode.getAttribute(attr));
    },
    getBooleanAttribute:function (xmlNode, attr) {
        return (xmlNode.getAttribute(attr).toLowerCase() == 'true');
    },
    getString:function (xmlElement, xmlNodeName, t) {
        try {
            var rawValue = xmlElement.getElementsByTagName(xmlNodeName)[0].childNodes[0].nodeValue;
        } catch (err) {
            //alert(Ext.String.format("XmlHelper.getString for {0} raised an error",xmlNodeName));
            return "";
        }
        if (t) {
            rawValue = Ext.String.trim(rawValue.toString());
        }
        return rawValue;
    },
    getInteger:function (xmlElement, xmlNodeName) {
        return parseInt(xmlElement.getElementsByTagName(xmlNodeName)[0].childNodes[0].nodeValue);
    },
    getFloat:function (xmlElement, xmlNodeName) {
        return parseFloat(xmlElement.getElementsByTagName(xmlNodeName)[0].childNodes[0].nodeValue);
    },
    getBoolean:function (xmlElement, xmlNodeName) {
        return (xmlElement.getElementsByTagName(xmlNodeName)[0].childNodes[0].nodeValue.toLowerCase() == 'true');
    },
    tryGetValue:function (xmlElement, xmlNodeName, option, defaultValue) {
        var rawValue = defaultValue;
        try {
            rawValue = xmlElement.getElementsByTagName(xmlNodeName)[0].childNodes[0].nodeValue;
        }
        catch (err) {
            return rawValue;
        }
        if (option == TryGetValueOption.Normal) {
            return rawValue;
        }
        if (option == TryGetValueOption.Trim) {
            return Ext.String.trim(rawValue);
        }
        if (option == TryGetValueOption.Boolean) {
            return rawValue.toLowerCase() == 'true';
        }
        if (option == TryGetValueOption.Integer) {
            return parseInt(rawValue);
        }
        if (option == TryGetValueOption.Float) {
            return parseFloat(rawValue);
        }
        return rawValue;
    }
};
Ext.define('AuthorPosition', {
    constructor:function (left, top) {
        this.Left = left;
        this.Top = top;
    },
    toString:function () {
        return "Left: " + this.Left + ", Top: " + this.Top;
    },
    clone:function () {
        return new AuthorPosition(this.Left, this.Top);
    }
});
Ext.define('GeneralAction', {
    constructor:function (cfgXML, o, actionSequence) {
        this.id = cfgXML.getAttribute('id');
        this.Name = Ext.String.trim(cfgXML.getAttribute('name'));
        this.ObjectType = cfgXML.getAttribute('type');
        this.Condition = null;
        this.ParentList = null;
        this.HasCondition = cfgXML.getAttribute('hasCondition').toLowerCase() == 'true';
        if (this.HasCondition) {
            var conditionNode = cfgXML.getElementsByTagName('condition')[0];
            this.Condition = new AuthorCondition(conditionNode);
        }
        //  this.LogicalOrder = (typeof(o) != 'undefined') ? o : null;
        this.LogicalOrder = new OrderClass(o.NodePath, 'Action', o.ElementSequence, o.ResponseID, o.ListType, actionSequence, this.ObjectType);
        //	alert(this.LogicalOrder);
        this.IsDisplayable = false;
        this.IsProcessed = false;
    },
    statics:{
        Version:15
    },
    processAction:function () {
        this.IsProcessed = true;
        return {MoveOn:true, Interval:0};
    },
    getEasingName: function ()
    {
        var name = "Linear";
        switch (this.Easing)
        {
            case Easings.BackIn:
                name = 'backIn';
                break;
            case Easings.BackOut:
                name = 'backOut';
                break;
            case Easings.BounceIn:
                name = 'bounceIn';
                break;
            case Easings.BounceOut:
                name = 'bounceOut';
                break;
            case Easings.Ease:
                name = 'ease';
                break;
            case Easings.EaseIn:
                    name = 'easeIn';
                    break;
            case Easings.EaseOut:
                    name = 'easeOut';
                    break;
            case Easings.EaseInOut:
                name = 'easeInOut';
                break;
            case Easings.ElasticIn:
                name = 'elasticIn';
                break;
            case Easings.ElasticOut:
                name = 'elasticOut';
                break;
            default:
                name = 'linear';
                break;
        }
        return name;
    },

    isConditionMatched:function () {

        return this.HasCondition ? this.Condition.isConditionMatched() : true;
    },
    getShortDescription:function () {
        return 'ID: ' + this.id + ", ActionType: " + this.ObjectType + ", List: " + this.LogicalOrder.ListType;
    },
    toString:function () {
        return 'ID: ' + this.id + ", ActionType: " + this.ObjectType + ", IsDisplayable: " + this.IsDisplayable + "\nOrder: " + this.LogicalOrder;
    },
    remove:function () {
    }
});
ChangeStackItemClass = function (changeActionID, changeActionOrder, isVisibleBeforeChange) {
    this.ChangeActionID = changeActionID;
    this.ChangeActionOrder = changeActionOrder;
    this.IsVisibleBeforeChange = isVisibleBeforeChange;
};
ChangeStackItemClass.prototype = {
    toString:function () {
        return Ext.String.format("Change by actionID: {0}\nOrder:\n{1}", this.ChangeActionID, this.ChangeActionOrder);
    }
};
Ext.define('DisplayableAction', {
    extend:'GeneralAction',
    constructor:function (cfgXML, o, actionSequence) {
        this.Width = 0;
        this.Height = 0;
        this.Left = 0;
        this.Top = 0;
        this.OriginalLeft = 0;
        this.OriginalTop = 0;
        this.BackgroundStyle = BackgroundStyles.Transparent;
        this.BackgroundShape = BackgroundShapes.Rectangle;
        this.BackgroundOpacity = 100;
        this.BackgroundColor = '#FFFFFF';
        this.GradientStartColor = '#FFFFFF';
        this.GradientEndColor = '#CCCCCC';
        this.GradientAngle = 0;
        this.IsInitialVisible = true;
        this.IsAddedToForeground = false;
        this.IsAddedToBackground = false;
        this.ContentMarginLeft = "0";
        this.ContentMarginRight = "0";
        this.ContentMarginTop = "0";
        this.ContentMarginBottom = "0";
        this.ContentContainerHeight = 0;
        this.CalculatedContentContainerHeight = 0;
        this.ContentContainerWidth = 0;
        this.CalculatedContentContainerWidth = 0;
        this.IsChangeAction = false;
        this.OrginalID = null;
        this.ChangeID = null;
        this.ChangedByID = null;
        this.Effect = AuthorEffects.NoEffect;
        this.EffectDuration = 0;
        this.Easing = Easings.Linear;
        this.BorderWidth = 0;
        this.BorderType = BorderTypes.Hidden;
        this.BorderColor = '#000000';
        this.RadiusX = 0;
        this.RadiusY = 0;
        this.HasShadow = false;
        this.ShadowX = 0;
        this.ShadowY = 0;
        this.ShadowBlurRadius = 0;
        this.ShadowColor = '#000000';
        this.IsVisible = false;
        this.VisibilityChangeStack = null;
        this.ChangeStack = null;
        this.ShadowLayer = null;

        this.DisplayableComponentContainer = null;
        this.DisplayableComponent = null;
        this.BackgroudLayer = null;
        this.BgRaphael = null;
        this.ContentContainer = null;
        this.callParent([ cfgXML, o, actionSequence]);
        this.IsDisplayable = true;
        this.VisibilityChangeStack = new Array();
        this.ChangeStack = new Array();
        var changeSettingNode = cfgXML.getElementsByTagName('changeSettings')[0];
        this.IsChangeAction = XmlHelper.getBooleanAttribute(changeSettingNode, "isChangeAction");
        this.OrginalID = XmlHelper.getStringAttribute(changeSettingNode, "orginalID");
        this.ChangeID = XmlHelper.getStringAttribute(changeSettingNode, "changeID");
        this.ChangedByID = XmlHelper.getStringAttribute(changeSettingNode, "changedByID");
        var displaySettingNode = cfgXML.getElementsByTagName('displaySettings')[0];
        this.Width = XmlHelper.getIntegerAttribute(displaySettingNode, "width");
        this.Height = XmlHelper.getIntegerAttribute(displaySettingNode, "height");
        this.Top = XmlHelper.getIntegerAttribute(displaySettingNode, "top");
        this.Left = XmlHelper.getIntegerAttribute(displaySettingNode, "left");
        this.OriginalLeft = this.Left;
        this.OriginalTop = this.Top;
        this.IsAddedToForeground = XmlHelper.getBooleanAttribute(displaySettingNode, "isAddedToForeground");
        this.IsAddedToBackground = XmlHelper.getBooleanAttribute(displaySettingNode, "isAddedToBackground");
        this.IsInitialVisible = XmlHelper.getBooleanAttribute(displaySettingNode, "isInitialVisible");
        var backgroundSettingNode = cfgXML.getElementsByTagName('backgroundSettings')[0];
        this.BackgroundStyle = XmlHelper.getIntegerAttribute(backgroundSettingNode, "backgroundStyle");
        this.BackgroundShape = XmlHelper.getIntegerAttribute(backgroundSettingNode, "backgroundShape");
        this.BackgroundOpacity = XmlHelper.getIntegerAttribute(backgroundSettingNode, "backgroundOpacity");
        this.BackgroundColor = XmlHelper.getStringAttribute(backgroundSettingNode, "backgroundColor");
        this.GradientStartColor = XmlHelper.getStringAttribute(backgroundSettingNode, "gradientStartColor");
        this.GradientEndColor = XmlHelper.getStringAttribute(backgroundSettingNode, "gradientEndColor");
        this.GradientAngle = XmlHelper.getIntegerAttribute(backgroundSettingNode, "gradientAngle");
        this.BorderColor = XmlHelper.getStringAttribute(backgroundSettingNode, "borderColor");
        this.BorderType = XmlHelper.getIntegerAttribute(backgroundSettingNode, "borderType");
        this.BorderWidth = XmlHelper.getIntegerAttribute(backgroundSettingNode, "borderWidth");
        this.RadiusX = XmlHelper.getIntegerAttribute(backgroundSettingNode, "radiusX");
        this.RadiusY = XmlHelper.getIntegerAttribute(backgroundSettingNode, "radiusY");
        this.ContentMarginLeft = XmlHelper.getIntegerAttribute(backgroundSettingNode, "contentMarginLeft");
        this.ContentMarginRight = XmlHelper.getIntegerAttribute(backgroundSettingNode, "contentMarginRight");
        this.ContentMarginTop = XmlHelper.getIntegerAttribute(backgroundSettingNode, "contentMarginTop");
        this.ContentMarginBottom = XmlHelper.getIntegerAttribute(backgroundSettingNode, "contentMarginBottom");
        var effectSettingNode = cfgXML.getElementsByTagName('effectSettings')[0];
        this.HasShadow = XmlHelper.getBooleanAttribute(effectSettingNode, "hasShadow");
        this.ShadowX = XmlHelper.getIntegerAttribute(effectSettingNode, "shadowX");
        this.ShadowY = XmlHelper.getIntegerAttribute(effectSettingNode, "shadowY");
        this.ShadowBlurRadius = XmlHelper.getIntegerAttribute(effectSettingNode, "shadowBlurRadius");
        this.ShadowColor = XmlHelper.getStringAttribute(effectSettingNode, "shadowColor");
        this.Effect = XmlHelper.getIntegerAttribute(effectSettingNode, "fxEffect");
        this.Easing = XmlHelper.getIntegerAttribute(effectSettingNode, "easing");
        this.EasingName = this.getEasingName();
        this.EffectDuration = XmlHelper.getFloatAttribute(effectSettingNode, "effectDuration") * 1000;
        this.ContentContainerWidth = this.Width - this.BorderWidth * 2 - this.ContentMarginLeft - this.ContentMarginRight;
        this.CalculatedContentContainerWidth = this.Width - this.BorderWidth * 2 - this.ContentMarginLeft - this.ContentMarginRight;
        this.ContentContainerHeight = this.Height - this.BorderWidth * 2 - this.ContentMarginTop - this.ContentMarginBottom;
        this.CalculatedContentContainerHeight = this.Height - this.BorderWidth * 2 - this.ContentMarginTop - this.ContentMarginBottom;
    },
    getContainerShadowStyle:function () {
        var str = "position:absolute;overflow:hidden;cursor:default;";
        str += "left:" + (this.Left - this.ShadowBlurRadius + this.ShadowX) + "px;top:" + (this.Top - this.ShadowBlurRadius + this.ShadowY) + "px;width:" + this.Width + "px;height:" + this.Height + "px;background-color:" + this.ShadowColor;
        str += ";filter: progid:DXImageTransform.Microsoft.Blur(pixelradius='" + this.ShadowBlurRadius + "')";
        str += " progid:DXImageTransform.Microsoft.Alpha( style=0,opacity=" + this.BackgroundOpacity + "); ";

        return str;
    },
    getDisplayComponentContainerStyle:function () {
        var strHead = "position:absolute;overflow:hidden;cursor:default;";
        var str = strHead + "left:" + this.Left + "px;top:" + this.Top + "px;width:" + this.Width + "px;height:" + this.Height + "px;";
        //   Author.log(Ext.String.format("Engine: {0}, isStrict: {1}",Author.Browser.engineName,Author.Browser.engineVersion));
        // alert(document.compatMode);
        if ((Ext.isIE && document.compatMode != 'BackCompat' && ( document.documentMode < 8 || Ext.browser.version < 8)) && this.BackgroundShape == BackgroundShapes.Rectangle) {
            str = strHead + "left:" + (this.Left) + "px;top:" + (this.Top) + "px;width:" + (this.Width - this.BorderWidth * 2) + "px;height:" + (this.Height - this.BorderWidth * 2) + "px;";
        }
        return str;
    },
    getContainerStyle:function () {
        var strHead = "position:absolute;overflow:hidden;cursor:default;";
        var str = strHead + "left:-2000px;top:0px;width:" + this.Width + "px;height:" + this.Height + "px;";
        //   Author.log(Ext.String.format("Engine: {0}, isStrict: {1}",Author.Browser.engineName,Author.Browser.engineVersion));
        // alert(document.compatMode);
        if ((Ext.isIE && document.compatMode != 'BackCompat' && ( document.documentMode < 8 || Ext.browser.version < 8)) && this.BackgroundShape == BackgroundShapes.Rectangle) {
            str = strHead + "left:-2000px;top:0px;width:" + (this.Width - this.BorderWidth * 2) + "px;height:" + (this.Height - this.BorderWidth * 2) + "px;";
        }
        return str;
    },
    getBackgroundStyle:function () {
        var str = "position:absolute;";
        str += "left:0px;top:0px;width:" + this.Width + "px;height:" + this.Height + "px";
        if (this.BackgroundShape == BackgroundShapes.Rectangle) {
            str += "left:0px;top:0px;width:" + (this.Width - this.BorderWidth * 2) + "px;height:" + (this.Height - this.BorderWidth * 2) + "px";
        }
        return str;
    },
    getContentStyle:function () {
        var contentX = this.BorderWidth + this.ContentMarginLeft;
        var contentY = this.BorderWidth + this.ContentMarginTop;
        if (this.BackgroundShape == BackgroundShapes.Rectangle) {
            contentX = this.ContentMarginLeft;
            contentY = this.ContentMarginTop;
        }
        //alert(this.ContentContainerWidth+", "+this.ContentContainerHeight);
        var str = "position:absolute;overflow:hidden;";
        str += "left:" + contentX + "px;top:" + contentY + "px;width:" + this.ContentContainerWidth + "px;height:" + this.ContentContainerHeight + "px;";
        str += "background-image:url('lib/images/spacer.gif');background-repeat:repeat; ";
        return str;
    },
    setCursor:function (cursorType) {
        if (typeof(cursorType) == 'undefined') {
            cursorType = CursorTypes.Default;
        }
        var cursorCss = "default";
        switch (cursorType) {
            case CursorTypes.Default:
                cursorCss = 'default';
                break;
            case CursorTypes.Crosshair:
                cursorCss = 'crosshair';
                break;
            case CursorTypes.Help:
                cursorCss = 'help';
                break;
            case CursorTypes.Move:
                cursorCss = 'move';
                break;
            case CursorTypes.NoDrop:
                cursorCss = 'no-drop';
                break;
            case CursorTypes.NotAllowed:
                cursorCss = 'not-allowed';
                break;
            case CursorTypes.Pointer:
                cursorCss = 'pointer';
                break;
            case CursorTypes.Progress:
                cursorCss = 'progress';
                break;
            case CursorTypes.Text:
                cursorCss = 'text';
                break;
            case CursorTypes.Wait:
                cursorCss = 'wait';
                break;
        }
        this.ContentContainer.setStyle("cursor", cursorCss);
    },
    setRectBorderStyle:function () {
        if (this.BackgroundLayer == null)
            return;
        var borderCSS = "border-width:" + this.BorderWidth + "px;";
        var bs = "hidden";
        switch (this.BorderType) {
            case BorderTypes.Solid:
                bs = "solid";
                break;
            case BorderTypes.Dashed:
                bs = "dashed";
                break;
            case BorderTypes.Dotted:
                bs = "dotted";
                break;
            case BorderTypes.DoubleBorder:
                bs = "double";
                break;
            case BorderTypes.Groove:
                bs = "groove";
                break;
            case BorderTypes.Ridge:
                bs = "ridge";
                break;
            case BorderTypes.Inset:
                bs = "inset";
                break;
            case BorderTypes.Outset:
                bs = "outset";
                break;
        }
        borderCSS += "border-style:" + bs + ";";
        try {
            var bc = Raphael.getRGB(this.BorderColor);
            var bcStr = Ext.String.format("rgba({0}, {1}, {2}, {3})", bc.r, bc.g, bc.b, this.BackgroundOpacity / 100.0);
            var borderStyle = borderCSS;
            borderCSS = borderStyle + "border-color: " + bcStr + ";";
            this.DisplayableComponent.applyStyles(borderCSS);
        } catch (err) {
            this.DisplayableComponent.applyStyles(borderStyle + "border-color: " + this.BorderColor + ";");
        }
    },
    setBackground:function () {
        if (this.BackgroundLayer == null) {
            return;
        }
        try {
            this.BgRaphael = Raphael(this.BackgroundLayer.dom, this.BackgroundLayer.getWidth(), this.BackgroundLayer.getHeight());
            this.setBackgroundRaphael();
        }
        catch (err) {
            this.setBackgroundNoRaphael();
        }
    },
    setBackgroundRaphael:function () {
        if (typeof(this.BgRaphael) == 'undefined')
        // if (typeof(this.BgDraw) == 'undefined')
            return;


        this.bgShape = null;
        var bw = this.BorderWidth;
        var dbw = this.BorderWidth * 2;
        var hbw = this.BorderWidth / 2.0;

        // this.BackgroundShape = BackgroundShapes.Hexagon;
        switch (this.BackgroundShape) {
            case BackgroundShapes.Rectangle:
                this.bgShape = this.BgRaphael.rect(0, 0, this.Width - dbw, this.Height - dbw);
                var bgHeight = this.BgRaphael.height;
                if (bgHeight < 12) {
                    Ext.get(this.ObjectType + "-" + this.id + "-background").setStyle('top', (bgHeight - 12) + 'px');
                }
                this.setRectBorderStyle();
                break;
            case BackgroundShapes.RoundedCornerRectangle:
                this.bgShape = this.BgRaphael.rect(hbw, hbw, this.Width - bw, this.Height - bw, this.RadiusX | this.RadiusY);
                break;
            case BackgroundShapes.Eclipse:
                var cx = this.Width / 2.0;
                var cy = this.Height / 2.0;
                //  if (((document.compatMode == 'BackCompat') && Ext.isIE)) {
                //      this.bgShape = this.BgRaphael.ellipse(cx, cy, cx - hbw - 1, cy - hbw - 1);
                //  }
                // else {
                this.bgShape = this.BgRaphael.ellipse(cx, cy, cx - hbw, cy - hbw);
                // }
                break;

            case BackgroundShapes.Octagon:
                var r = 0.29289;
                var ry = (this.Height - hbw) * r;
                var rx = (this.Width - hbw) * r;
                var pathTemplate = "M {0} {1}L{2} {3}L{4} {5}L{6} {7}L{8} {9}L{10} {11}L{12} {13}L{14} {15} Z";
                var path = Ext.String.format(pathTemplate, hbw, ry, rx, hbw, this.Width - rx, hbw, this.Width - hbw, ry, this.Width - hbw, this.Height - ry, this.Width - rx, this.Height - hbw, rx, this.Height - hbw, hbw, this.Height - ry);
                this.bgShape = this.BgRaphael.path(path);
                break;
            case BackgroundShapes.TriangleRight:
                var pathTemplate = "M{0} {1}L{2} {3}L{4} {5} Z";
                var path = Ext.String.format(pathTemplate, hbw, hbw, (this.Width - hbw), (this.Height - hbw) / 2, hbw, (this.Height - hbw));
                this.bgShape = this.BgRaphael.path(path);
                break;
            case BackgroundShapes.TriangleUp:
                var pathTemplate = "M{0} {1}L{2} {3}L{4} {5} Z";
                var path = Ext.String.format(pathTemplate, hbw, (this.Height - hbw), (this.Width - hbw) / 2, hbw, (this.Width - hbw), (this.Height - hbw));
                this.bgShape = this.BgRaphael.path(path);
                break;
            case BackgroundShapes.TriangleLeft:
                var pathTemplate = "M{0} {1}L{2} {3}L{4} {5} Z";
                var path = Ext.String.format(pathTemplate, hbw, (this.Height - hbw) / 2, (this.Width - hbw), hbw, (this.Width - hbw), (this.Height - hbw));
                this.bgShape = this.BgRaphael.path(path);
                break;
            case BackgroundShapes.TriangleDown:
                var pathTemplate = "M{0} {1}L{2} {3}L{4} {5} Z";
                var path = Ext.String.format(pathTemplate, hbw, hbw, (this.Width - hbw), hbw, (this.Width - hbw) / 2, (this.Height - hbw));
                this.bgShape = this.BgRaphael.path(path);
                break;
            case BackgroundShapes.Diamond:
                var pathTemplate = "M{0} {1}L{2} {3}L{4} {5}L{6} {7} Z";
                var path = Ext.String.format(pathTemplate, hbw, (this.Height - hbw) / 2, (this.Width - hbw) / 2, hbw, (this.Width - hbw), (this.Height - hbw) / 2, (this.Width - hbw) / 2, (this.Height - hbw));
                this.bgShape = this.BgRaphael.path(path);
                break;
            case BackgroundShapes.Hexagon:
                var r = 0.2257;
                var ry = (this.Height - hbw) / 2;
                var rx = (this.Width - hbw) * r;
                var pathTemplate = "M {0} {1}L{2} {3}L{4} {5}L{6} {7}L{8} {9}L{10} {11} Z";
                var path = Ext.String.format(pathTemplate, hbw, ry, rx, hbw, this.Width - rx, hbw, this.Width - hbw, ry, this.Width - rx, this.Height - hbw, rx, this.Height - hbw);
                this.bgShape = this.BgRaphael.path(path);
                break;
            default:
                this.bgShape = this.BgRaphael.rect(-1, -1, this.Width - dbw + 2, this.Height - dbw + 2);
                Author.LessonManager.log(Ext.String.format("setBackgroundRaphael, backgroundShape: {0} has not been implemented. ", this.BackgroundShape));
        }
        switch (this.BackgroundStyle) {
            case BackgroundStyles.Transparent:
                this.bgShape.attr({
                    'fill-opacity':0,
                    'stroke-width':0,
                    'stroke-opacity':0
                });
                break;
            case BackgroundStyles.Solid:
                //   alert("solid");
                if (this.BackgroundColor != 'transparent') {
                    this.bgShape.attr({
                        fill:this.BackgroundColor,
                        'fill-opacity':this.BackgroundOpacity / 100.0,
                        'stroke-width':0,
                        'stroke-opacity':0
                    });
                } else {
                    this.bgShape.attr({
                        'fill-opacity':0,
                        'stroke-width':0,
                        'stroke-opacity':0
                    });
                }

                break;
            case BackgroundStyles.LinearGradient:
                this.bgShape.attr({
                    gradient:(360 - this.GradientAngle) + "-" + this.GradientStartColor + "-" + this.GradientEndColor,
                    'fill-opacity':this.BackgroundOpacity / 100.0
                });
                break;
            case BackgroundStyles.RadialGradient:
                // alert("r" + this.GradientStartColor + "-" + this.GradientEndColor);
                this.bgShape.attr({
                    gradient:"r" + this.GradientStartColor + "-" + this.GradientEndColor,
                    'fill-opacity':this.BackgroundOpacity / 100.0
                });
                break;
        }
        if (this.BackgroundShape != BackgroundShapes.Rectangle) {
            var dashArrayStr = "";
            switch (this.BorderType) {
                case BorderTypes.Dotted:
                    dashArrayStr = ".";
                    break;
                case BorderTypes.Dashed:
                    dashArrayStr = "-";
                    break;
            }
            this.bgShape.attr({
                stroke:this.BorderColor,
                'stroke-opacity':(this.BorderWidth == 0 ? 0 : this.BackgroundOpacity / 100.0),
                'stroke-width':this.BorderWidth,
                'stroke-dasharray':dashArrayStr
            })
        }
    },
    fillBackground:function (color, startColor, endColor) {
        if (this.bgShape == null){
            return;
        }
        switch (this.BackgroundStyle) {
            case BackgroundStyles.Transparent:
                break;
            case BackgroundStyles.Solid:
                //   alert("solid");
                if (color.toLowerCase() != 'transparent') {
                    this.bgShape.attr({
                        fill:color,
                        'fill-opacity':this.BackgroundOpacity / 100.0,
                        'stroke-width':0,
                        'stroke-opacity':0
                    });
                } else {
                    this.bgShape.attr({
                        fill:""
                    });
                }
                break;
            case BackgroundStyles.LinearGradient:
                this.bgShape.attr({
                    gradient:(360 - this.GradientAngle) + "-" + startColor + "-" + endColor,
                    'fill-opacity':this.BackgroundOpacity / 100.0
                });
                break;
            case BackgroundStyles.RadialGradient:
                // alert("r" + this.GradientStartColor + "-" + this.GradientEndColor);
                this.bgShape.attr({
                    gradient:"r" + startColor + "-" + endColor,
                    'fill-opacity':this.BackgroundOpacity / 100.0
                });
                break;
        }
        if (this.BackgroundShape != BackgroundShapes.Rectangle) {
            var dashArrayStr = "";
            switch (this.BorderType) {
                case BorderTypes.Dotted:
                    dashArrayStr = ".";
                    break;
                case BorderTypes.Dashed:
                    dashArrayStr = "-";
                    break;
            }
            this.bgShape.attr({
                stroke:this.BorderColor,
                'stroke-opacity':(this.BorderWidth == 0 ? 0 : this.BackgroundOpacity / 100.0),
                'stroke-width':this.BorderWidth,
                'stroke-dasharray':dashArrayStr
            })
        }
    },

    setBackgroundNoRaphael:function () {
        Author.log("No raphael supported");
    },
    getPosition:function () {
        if (this.DisplayableComponentContainer != null) {
            return new AuthorPosition(this.DisplayableComponentContainer.getLeft(true), this.DisplayableComponentContainer.getTop(true));
        }
        return null;
    },
    getContentPosition:function () {
        if (this.ContentContainer != null) {
            return new AuthorPosition(this.ContentContainer.getLeft(true), this.ContentContainer.getTop(true));
        }
        return null;
    },
    initializeDisplayComponent: function (bgObject) {
        
        if (this.ObjectType != "BACKGROUND") {
            if (Ext.isIE && document.documentMode < 9 && this.HasShadow && this.BackgroundShape == BackgroundShapes.Rectangle) {
                this.ShadowLayer = bgObject.createChild({
                    tag:'div',
                    tabindex:-1,
                    id:this.ObjectType + "-" + this.id + "-shadow",
                    style:this.getContainerShadowStyle()
                });
                this.ShadowLayer.hide();
            }
        }
        this.DisplayableComponentContainer = bgObject.createChild({
            tag:"div",
            tabindex:-1,
            id:this.ObjectType + "-" + this.id + "-container",
            cls:"AUTHOR_" + this.ObjectType + "-container",
            style:this.getDisplayComponentContainerStyle()
        });

        this.DisplayableComponent = this.DisplayableComponentContainer.createChild({
            tag:"div",
            id:this.ObjectType + "-" + this.id,
            cls:"AUTHOR_" + this.ObjectType,
            tabindex:-1, //this.id,
            style:this.getContainerStyle()
        });
        if (this.ObjectType != "BACKGROUND") {
            this.BackgroundLayer = this.DisplayableComponent.createChild({
                tag:"div",
                tabindex:"-1",
                id:this.ObjectType + "-" + this.id + "-background",
                style:this.getBackgroundStyle()
            });
            this.setBackground();
        }
        //Setup content;\
        this.ContentContainerID = this.ObjectType + "-" + this.id + "-content";

        this.ContentContainer = this.DisplayableComponent.createChild({
            tag:"div",
            tabindex:-1,
            id:this.ContentContainerID,
            style:this.getContentStyle()
        });

    },

    applyShadow:function () {
        if (this.DisplayableComponentContainer == null)
            return;
        if (!this.HasShadow || this.BackgroundShape != BackgroundShapes.Rectangle)
            return;
        var shadowCSS = this.ShadowX + "px " + this.ShadowY + "px " + this.ShadowBlurRadius + "px " + this.ShadowColor;
        var shadowStyle = '-moz-box-shadow:' + shadowCSS + ";-webkit-box-shadow:" + shadowCSS + ";box-shadow:" + shadowCSS;
        this.DisplayableComponentContainer.applyStyles(shadowStyle);
    },
    setInitialVisibility:function () {
        this.VisibilityChangeStack = new Array();
        if (this.IsInitialVisible) {
            this.show();
        }
        else {
            this.hide();
        }
    },
    setVisible:function () {
        //if (Ext.isIE && this.HasShadow && this.BackgroundShape == BackgroundShapes.Rectangle) {
        if (this.ShadowLayer != null) {
            this.ShadowLayer.setVisible(this.IsVisible);
        }
        //}
        if (this.DisplayableComponentContainer != null) {
            this.DisplayableComponentContainer.setVisible(this.IsVisible);
        }
    },
    show:function () {
        this.IsVisible = true;
        this.setVisible();
    },
    hide:function () {
        this.IsVisible = false;
        this.setVisible();
    },
    getCssPosition:function () {
        var pos = {Left:this.Left, Top:this.Top, IsValid:false};
        if (this.DisplayableComponentContainer != null) {
            pos.Left = this.DisplayableComponentContainer.getLeft(true);
            pos.Top = this.DisplayableComponentContainer.getTop(true);
            pos.IsValid = true;
        }
        return pos;

    },
    moveTo:function (left, top, doNotChangeCurrent) {
        if(!doNotChangeCurrent){
            this.Left = left;
            this.Top = top;
        }

        if (this.ShadowLayer != null) {
            // if (Ext.isIE && this.HasShadow && this.BackgroundShape == BackgroundShapes.Rectangle && this.ShadowLayer != null) {
            this.ShadowLayer.applyStyles("left:" + (left - this.ShadowBlurRadius + this.ShadowX) + "px;top:" + (top - this.ShadowBlurRadius + this.ShadowY) + "px;width:" + this.Width + "px;");
        }
        if (this.DisplayableComponentContainer != null) {
            this.DisplayableComponentContainer.applyStyles("left:" + (left) + "px;top:" + (top) + "px;");
        }
    },
    setZIndex:function (zindex) {
        if (this.ShadowLayer != null) {
            //  if (Ext.isIE && this.HasShadow && this.BackgroundShape == BackgroundShapes.Rectangle && this.ShadowLayer != null) {
            this.ShadowLayer.setStyle("z-index", zindex);
        }
        if (this.DisplayableComponentContainer != null) {
            this.DisplayableComponentContainer.setStyle("z-index", zindex);
        }
    },
    getCurrentPosition:function () {
        return new AuthorPosition(this.DisplayableComponentContainer.getLeft(true), this.DisplayableComponentContainer.getTop(true));
    },
    toString:function () {
        var str = 'ID: ' + this.id + ", ActionType: " + this.ObjectType + ", IsDisplayable: " + this.IsDisplayable;
        str += "\nWidth: " + this.Width + ", Height: " + this.Height + ", Left: " + this.Left + ", Top: " + this.Top;
        str += "\nBorderWidth: " + this.BorderWidth + ", BorderColor: " + this.BorderColor;
        str += "\nMLeft: " + this.ContentMarginLeft + ", MRight: " + this.ContentMarginRight + ", MTop: " + this.ContentMarginTop + ", MBottom: " + this.ContentMarginBottom;
        str += "\nContentContainerWidth: " + this.ContentContainerWidth + ", ContentContainerHeight: " + this.ContentContainerHeight;
        str += "\nHasShadow: " + this.HasShadow + ", ( " + this.ShadowX + ", " + this.ShadowY + ", " + this.ShadowBlurRadius + "), ShadowColor: " + this.ShadowColor;
        str += "\nIsAddedToBackground: " + this.IsAddedToBackground + ", IsAddedToForeground: " + this.IsAddedToForeground;
        str += "\nIsChangeAction: " + this.IsChangeAction;
        str += "\n\nOrder:\n" + this.LogicalOrder;
        return str;
    },
    processAction:function () {
        this.IsProcessed = true;
        return {MoveOn:true, Interval:0};
    },


    applyEffect:function () {

        // this.Effect = AuthorEffects.SlideUp;
        switch (this.Effect) {
            case AuthorEffects.NoEffect:
                this.onEffectCompleted();
                return 0;
            case AuthorEffects.FadeIn:
                return  this.doFadeInEffect();
            case AuthorEffects.Highlight:
                return  this.doHighLightEffect();
            case AuthorEffects.ZoomOut:
                return this.doZoomOutEffect();
            default:
                return  this.doSlideEffect();
        }
    },
    onEffectCompleted:function () {
        if (this.DisplayableComponent != null) {
            this.DisplayableComponent.setStyle("left", "0px");
            if (this.ObjectType != "BACKGROUND") {
                this.applyShadow();
            }
            if (this.ShadowLayer != null) {
                this.ShadowLayer.show();
            }
        }
    },
    onEffectStarted:function () {

        if (this.DisplayableComponent != null) {
            if (this.ShadowLayer != null) {
                this.ShadowLayer.hide();
            }
            this.DisplayableComponent.setStyle("left", "0px");
        }
    },
    doFadeInEffect:function () {
        this.DisplayableComponent.setStyle("opacity", 0);
        this.DisplayableComponent.setStyle("left", "0px");
        if (this.ShadowLayer != null) {
            this.ShadowLayer.hide();
        }
        this.DisplayableComponent.fadeIn({
            opacity:1,
            duration:this.EffectDuration,
            callback:this.onEffectCompleted,
            easing: this.EasingName,
            listeners:{
                beforeanimate:{fn:this.onEffectStarted, scope:this}
            },
            scope:this

        });
        return this.EffectDuration;
    },
    doHighLightEffect:function () {
        this.DisplayableComponent.setStyle("left", "0px");
        this.DisplayableComponent.frame(this.BorderColor, 3, {
            duration:this.EffectDuration / 3,
            callback:this.onEffectCompleted,
            listeners:{
                beforeanimate:{fn:this.onEffectStarted, scope:this}
            },
            scope:this
        });
        return this.EffectDuration;
    },
    doZoomOutEffect:function () {
        var sx, sy, sw, sh, ex, ey, ew, eh;
        sx = this.Width / 2;
        sy = this.Height / 2;
        sw = 0;
        sh = 0;
        ex = 0;
        ey = 0;
        ew = this.Width;
        eh = this.Height;
        Ext.create('Ext.fx.Anim', {
            target:this.DisplayableComponent,
            duration:this.EffectDuration,
         
            from:{
                left:sx,
                top:sy,
                width:sw,
                height:sh
            }, to:{
                left:ex,
                top:ey,
                width:ew,
                height:eh
            },
            callback:this.onEffectCompleted,
            listeners:{
                beforeanimate:{fn:this.onEffectStarted, scope:this}
            },
            scope:this
        });

        return this.EffectDuration;
    },
    doSlideEffect:function () {
        var sx, sy, sw, sh, ex, ey, ew, eh;
        // Author.log(Ext.String.format("Apply Effect [{2}-{3}]: {0}, duration {1}", this.Effect, this.EffectDuration, this.ObjectType, this.id));
        switch (this.Effect) {
            case AuthorEffects.SlideUp:
                sx = 0;
                sy = this.Height;
                sw = this.Width;
                sh = this.Height;
                ex = 0;
                ey = 0;
                ew = this.Width;
                eh = this.Height;
                break;
            case AuthorEffects.SlideDown:
                sx = 0;
                sy = -this.Height;
                sw = this.Width;
                sh = this.Height;
                ex = 0;
                ey = 0;
                ew = this.Width;
                eh = this.Height;
                break;
            case AuthorEffects.SlideLeft:
                sx = this.Width;
                sy = 0;
                sw = this.Width;
                sh = this.Height;
                ex = 0;
                ey = 0;
                ew = this.Width;
                eh = this.Height;
                break;
            case AuthorEffects.SlideRight:
                sx = -this.Width;
                sy = 0;
                sw = this.Width;
                sh = this.Height;
                ex = 0;
                ey = 0;
                ew = this.Width;
                eh = this.Height;
                break;
            case AuthorEffects.SlideTLBR:
                sx = -this.Width;
                sy = -this.Height;
                sw = this.Width;
                sh = this.Height;
                ex = 0;
                ey = 0;
                ew = this.Width;
                eh = this.Height;
                break;
            case AuthorEffects.SlideTRBL:
                sx = this.Width;
                sy = this.Height;
                sw = this.Width;
                sh = this.Height;
                ex = 0;
                ey = 0;
                ew = this.Width;
                eh = this.Height;
                break;
            case AuthorEffects.SlideBLTR:
                sx = -this.Width;
                sy = this.Height;
                sw = this.Width;
                sh = this.Height;
                ex = 0;
                ey = 0;
                ew = this.Width;
                eh = this.Height;
                break;
            case AuthorEffects.SlideBRTL:
                sx = this.Width;
                sy = this.Height;
                sw = this.Width;
                sh = this.Height;
                ex = 0;
                ey = 0;
                ew = this.Width;
                eh = this.Height;
                break;
        }
        Ext.create('Ext.fx.Anim', {
            
            target:this.DisplayableComponent,
            duration:this.EffectDuration,
            easing: this.EasingName,
            from:{
                left:sx,
                top:sy,
                width:sw,
                height:sh
            }, to:{
                left:ex,
                top:ey,
                width:ew,
                height:eh
            },
            callback:this.onEffectCompleted,
            listeners:{
                beforeanimate:{fn:this.onEffectStarted, scope:this}
            },
            scope:this

        });
        return this.EffectDuration;
    },
    getShortDescription:function () {
        return 'ID: ' + this.id + ", " + this.ObjectType + ", List: " + this.LogicalOrder.ListType + (this.IsAddedToBackground ? ", B" : "") + (this.IsAddedToForeground ? ", F" : "") + (this.IsVisible ? ", visible" : ", hidden") + (this.IsChangeAction ? ", change " : "");
    },
    removeDisplayableComponent:function () {
        if (this.ShadowLayer != null) {
            this.ShadowLayer.remove();
            this.ShadowLayer = null;
        }
        if (this.DisplayableComponent != null) {
            this.DisplayableComponent.remove();
            this.DisplayableComponent = null;
        }
        if (this.DisplayableComponentContainer != null) {
            this.DisplayableComponentContainer.remove();
            this.DisplayableComponentContainer = null;
        }
    },
    remove:function () {
        this.removeDisplayableComponent();
        if (this.IsChangeAction) {
            var orginalAction = Author.CurrentStateManager.getActionByID(this.OrginalID);
            if (orginalAction) {
                orginalAction.fixActionChangeAtOrder(this.LogicalOrder);
            }
            else {
                Author.log("remove.fixchangeaction.can't find orginal action");
            }
        }
    },
    applyChange:function (changeAction) {
        var lastChangeAction = this.ChangeStack.peek();
        if (lastChangeAction == null) {
            lastChangeAction = this;
        }
        else {
            lastChangeAction = Author.CurrentStateManager.getActionByID(lastChangeAction.ChangeActionID);
            if (lastChangeAction == null) {
                Author.log("Can't find lastChangeAction");
                return;
            }
        }
        var changeStackItem = new ChangeStackItemClass(changeAction.id, changeAction.LogicalOrder, this.IsVisible);
        this.ChangeStack.push(changeStackItem);
        //   Author.log(Ext.String.format("Push into changestack, ChangeActionID: {0}, actionType: {2}, NewLength: {1}", changeStackItem.ChangeActionID, this.ChangeStack.length, this.ObjectType));
        changeAction.doActionChange(lastChangeAction);
    },
    doActionChange:function (changingAction) {
        //Author.log(Ext.String.format("Change action from {0} to {1}, actionType: {2}, isVisibleBeforeChange: {3}", changingAction.id, this.id, this.ObjectType, changingAction.IsVisible));
        var actionToChange = Author.CurrentStateManager.getActionByID(changingAction.id);
        if (actionToChange) {
            actionToChange.hide();
        }
        else {
            Author.log("Try to change an action that not in current action list.");
        }
    },
    restoreToAction:function (toAction, isVisibleBeforeChange) {
        // Author.log(Ext.String.format("Restore action {0} to {1}, actionType: {2}, isVisibleBeforeChange: {3}.", this.id, toAction.id, this.ObjectType, isVisibleBeforeChange));
        var actionToRestore = Author.CurrentStateManager.getActionByID(toAction.id);
        if (actionToRestore) {
            if (isVisibleBeforeChange) {
                actionToRestore.show();
            }
            else {
                actionToRestore.hide();
            }
        }
        else {
            Author.log("Try to retore an action that not in current action list.");
        }
    },
    isChangedByAnotherAction:function () {
        return this.ChangeStack.length > 0;
    },
    fixActionChangeAtOrder:function (order) {
        if (this.IsChangeAction) {
           // Author.log("Change action can't fixActionChange.\n" + this);
            return;
        }
        var top = this.ChangeStack.peek();
        if (top == null) {
            return;
        }
        var compareResult = top.ChangeActionOrder.compareTo(order);
        if (compareResult < 0) {
            return;
        }
        var doWhile = true;
        while (doWhile) {
            this.ChangeStack.pop();
            if (this.ChangeStack.length > 0) {
                top = this.ChangeStack.peek();
                compareResult = top.ChangeActionOrder.compareTo(order);
                doWhile = compareResult >= 0;
            }
            else {
                doWhile = false;
            }
        }
        top = this.ChangeStack.peek();
        if (top == null) {
            // Author.log(Ext.String.format('Restore {0} from {1}, orginal. {2}', this.OrginalID, this.id,this.ObjectType));
            Author.DisplayManager.restoreAction(this, this.OrginalID, this.IsInitialVisible);
        }
        else {
            //  Author.log(Ext.String.format('Restore {0} from {1}. {2}', top.ChangeActionID, this.id,this.ObjectType));
            Author.DisplayManager.restoreAction(this, top.ChangeActionID, top.IsVisibleBeforeChange);
        }
    },
    fixVisibilityAtOrder:function (order) {
        var top = this.VisibilityChangeStack.peek();
        if (top == null) {
            return;
        }
        var compareResult = top.OrderOfChange.compareTo(order);
        if (compareResult < 0) {
            return;
        }
        var doWhile = true;
        while (doWhile) {
            this.VisibilityChangeStack.pop();
            if (this.VisibilityChangeStack.length > 0) {
                top = this.VisibilityChangeStack.peek();
                compareResult = top.OrderOfChange.compareTo(order);
                doWhile = compareResult >= 0;
            }
            else {
                doWhile = false;
            }
        }
        top = this.VisibilityChangeStack.peek();
        if (top != null) {
            //Author.log(Ext.String.format("Action {1} visibility restore to {0} by visibleAction {2}", top.NewIsVisible, this.id, top.VisibleActionID));
            if (top.NewIsVisible) {
                this.show();
            }
            else {
                this.hide();
            }
        }
        else {
            // Author.log("setInitialVisibility");
            this.setInitialVisibility();
        }
    },
    getLastChangeActionBeforeOrder:function (order) {
        if (this.IsChangeAction) {
            Author.log("getLastChangeActionBeforeOrder.Should not happen");
            return;
        }
        if (this.ChangeStack.length == 0) {
            return this;
        }
        var i = 0, lastChangeActionID = -1;
        while (i < this.ChangeStack.length && this.ChangeStack[i].ChangeActionOrder.compareTo(order) < 0) {
            lastChangeActionID = this.ChangeStack[i].ChangeActionID;
            i++;
        }
        if (lastChangeActionID >= 0) {
            return Author.CurrentStateManager.getActionByID(lastChangeActionID);
        }
    },
    applyVisibilityChange:function (o, visibilityChangeObject) {

        if (this.IsChangeAction) {
            Author.log("applyVisibilityChange.Should not happen");
            return;
        }
        var lastChangedAction = this.getLastChangeActionBeforeOrder(o);

        if (lastChangedAction == null) {
            Author.log('should not happen');
            return;
        }
        var visibilityStackItem = new VisibilityStackItemClass(o, visibilityChangeObject.TargetIsVisible, this.IsVisible, visibilityChangeObject.VisibleActionID);
        if (visibilityStackItem.NewIsVisible) {
            lastChangedAction.show();
        }
        else {
            lastChangedAction.hide();
        }
        // Author.log(Ext.String.format("Push into action {1} VisibilityChangeStack, to {0} by {2}", visibilityStackItem.NewIsVisible, this.id, visibilityStackItem.VisibleActionID));
        this.VisibilityChangeStack.push(visibilityStackItem);
    }
});
