"use strict";

//-----------------------------------------------------------------------------------
// Global counters
//-----------------------------------------------------------------------------------

var locktype_None   = 1; // никто не залочил данный объект
var locktype_Mine   = 2; // данный объект залочен текущим пользователем
var locktype_Other  = 3; // данный объект залочен другим(не текущим) пользователем
var locktype_Other2 = 4; // данный объект залочен другим(не текущим) пользователем (обновления уже пришли)
var locktype_Other3 = 5; // данный объект был залочен (обновления пришли) и снова стал залочен

function CLock()
{
    this.Type   = locktype_None;
    this.UserId = null;

    this.Get_Type = function()
    {
        return this.Type;
    };

    this.Set_Type = function(NewType, Redraw)
    {
        if ( NewType === locktype_None )
            this.UserId = null;

        this.Type = NewType;

        if ( false != Redraw )
        {
            // TODO: переделать перерисовку тут
            var DrawingDocument = editor.WordControl.m_oLogicDocument.DrawingDocument;
            DrawingDocument.ClearCachePages();
            DrawingDocument.FirePaint();
        }
    };

    this.Check = function(Id)
    {
        if ( this.Type === locktype_Mine )
            CollaborativeEditing.Add_CheckLock( false );
        else if ( this.Type === locktype_Other || this.Type === locktype_Other2 || this.Type === locktype_Other3 )
            CollaborativeEditing.Add_CheckLock( true );
        else
            CollaborativeEditing.Add_CheckLock( Id );
    };

    this.Lock = function(bMine)
    {
        if ( locktype_None === this.Type )
        {
            if ( true === bMine )
                this.Type = locktype_Mine;
            else
                true.Type = locktype_Other;
        }
    };

    this.Is_Locked = function()
    {
        if ( locktype_None != this.Type && locktype_Mine != this.Type )
            return true;

        return false;
    };

    this.Set_UserId = function(UserId)
    {
        this.UserId = UserId;
    };

    this.Get_UserId = function()
    {
        return this.UserId;
    };

    this.Have_Changes = function()
    {
        if ( locktype_Other2 === this.Type || locktype_Other3 === this.Type )
            return true;

        return false;
    };
}

function CIdCounter()
{
    this.m_sUserId        = null;
    this.m_bLoad          = true;
    this.m_nIdCounterLoad = 0; // Счетчик Id для загрузки
    this.m_nIdCounterEdit = 0; // Счетчик Id для работы

    this.Get_NewId = function()
    {
        if ( true === this.m_bLoad || null === this.m_sUserId )
        {
            this.m_nIdCounterLoad++;
            return ("" + this.m_nIdCounterLoad);
        }
        else
        {
            this.m_nIdCounterEdit++;
            var cur_id =  ("" + this.m_sUserId + "_" + this.m_nIdCounterEdit);
            while(isRealObject(g_oTableId.Get_ById(cur_id)))
            {
                this.m_nIdCounterEdit++;
                cur_id =  ("" + this.m_sUserId + "_" + this.m_nIdCounterEdit);
            }
            return cur_id;
        }
    };

    this.Set_UserId = function(sUserId)
    {
        this.m_sUserId = sUserId;
    };

    this.Set_Load = function(bValue)
    {
        this.m_bLoad = bValue;
    };
}

function CTableId()
{
    this.m_aPairs   = {};
    this.m_bTurnOff = false;


    this.Id = g_oIdCounter.Get_NewId();
    this.Add(this, this.Id);
}



CTableId.prototype =
{
    getObjectType: function()
    {
        return CLASS_TYPE_TABLE_ID;
    },

    Add: function(Class, Id, sheetId)
    {
        if ( false === this.m_bTurnOff )
        {
            Class.Id = Id;
            this.m_aPairs[Id] = Class;
            if(Class !== this && History instanceof CHistory)
                History.Add(g_oUndoRedoGraphicObjects, historyitem_TableId_Add, null, null, new UndoRedoDataGraphicObjects(this.Get_Id(), new UndoRedoData_GTableIdAdd(Class, Id)));
        }
    },


    Get_ById: function(Id)
    {
        if ( "undefined" != typeof(this.m_aPairs[Id]) )
            return this.m_aPairs[Id];

        return null;
    },

    Get_ByClass: function(Class)
    {
        if ( "undefined" != typeof( Class.Get_Id ) )
            return Class.Get_Id();

        if ( "undefined" != typeof( Class.GetId() ) )
            return Class.GetId();

        return null;
    },

    Reset_Id: function(Class, Id_new, Id_old)
    {
        if ( Class === this.m_aPairs[Id_old] )
        {
            delete this.m_aPairs[Id_old];
            this.m_aPairs[Id_new] = Class;

            History.Add( this, { Type : historyitem_TableId_Reset, Id_new : Id_new, Id_old : Id_old  } );
        }
        else
        {
            this.Add( Class, Id_new );
        }
    },

    Get_Id: function()
    {
        return this.Id;
    },
//-----------------------------------------------------------------------------------
// Функции для работы с Undo/Redo
//-----------------------------------------------------------------------------------
    Undo: function(Data)
    {
        // Ничего не делаем (можно удалять/добавлять ссылки на классы в данном классе
        // но это не обяательно, т.к. Id всегда уникальные)
    },

    Redo: function(type, data)
    {
        switch(type)
        {
            case historyitem_TableId_Add:
            {
                if(isRealObject(this.m_aPairs[data.id]) && this.m_aPairs[data.id].Id === data.id)
                    break;
                this.m_bTurnOff = true;
                var Id    = data.id;
                var  Class;
                switch (data.objectType)
                {
                    case CLASS_TYPE_SHAPE:
                    {
                        Class = new CShape();
                        break;
                    }
                    case CLASS_TYPE_XFRM:
                    {
                        Class = new CXfrm();
                        break;
                    }
                    case CLASS_TYPE_GEOMETRY:
                    {
                        Class = new CGeometry();
                        break;
                    }

                    case CLASS_TYPE_IMAGE:
                    {
                        Class = new CImageShape();
                        break;
                    }

                    case CLASS_TYPE_GROUP:
                    {
                        Class = new CGroupShape();
                        break;
                    }
                    case CLASS_TYPE_PATH:
                    {
                        Class = new Path();
                        break;
                    }
                    case CLASS_TYPE_PARAGRAPH:
                    {
                        Class = new Paragraph();
                        break;
                    }
                    case CLASS_TYPE_TEXT_BODY:
                    {
                        Class = new CTextBody();
                        break;
                    }
                    case CLASS_TYPE_DOCUMENT_CONTENT:
                    {
                        Class = new CDocumentContent();
                        break;
                    }
                    case CLASS_TYPE_TEXT_PR:
                    {
                        Class = new ParaTextPr();
                        break;
                    }

                    case CLASS_TYPE_UNI_FILL:
                    {
                        Class = new CUniFill();
                        break;
                    }

                    case CLASS_TYPE_PATTERN_FILL:
                    {
                        Class = new CPattFill();
                        break;
                    }
                    case CLASS_TYPE_GRAD_FILL:
                    {

                        Class = new CGradFill();
                        break;
                    }
                    case CLASS_TYPE_SOLID_FILL:
                    {

                        Class = new CSolidFill();
                        break;
                    }
                    case CLASS_TYPE_UNI_COLOR:
                    {

                        Class = new CUniColor();
                        break;
                    }
                    case CLASS_TYPE_SCHEME_COLOR :
                    {
                        Class = new CSchemeColor();
                        break;
                    }
                    case CLASS_TYPE_RGB_COLOR:
                    {
                        Class = new CRGBColor();
                        break;
                    }
                    case CLASS_TYPE_PRST_COLOR:
                    {
                        Class = new CPrstColor();
                        break;
                    }
                    case CLASS_TYPE_SYS_COLOR:
                    {
                        Class = new CSysColor();
                        break;
                    }
                    case CLASS_TYPE_LINE:
                    {
                        Class = new CLn();
                        break;
                    }
                    case CLASS_TYPE_CHART_AS_GROUP:
                    {
                        Class = new CChartAsGroup();
                        break;
                    }
                    case CLASS_TYPE_CHART_LEGEND:
                    {
                        Class = new CChartLegend();
                        break;
                    }
                    case CLASS_TYPE_CHART_TITLE:
                    {
                        Class = new CChartTitle();
                        break;
                    }
                    case CLASS_TYPE_COLOR_MOD:
                    {
                        Class = new CColorMod();
                        break;
                    }
                    case CLASS_TYPE_LEGEND_ENTRY:
                    {
                        Class = new CLegendEntry();
                        break;
                    }
                    case CLASS_TYPE_NO_FILL:
                    {
                        Class = new CNoFill();
                        break;
                    }
                    case CLASS_TYPE_GS:
                    {
                        Class = new CGs();
                        break;
                    }
                    case CLASS_TYPE_BLIP_FILL:
                    {
                        Class = new CBlipFill();
                        break;
                    }
                    case CLASS_TYPE_GRAD_LIN:
                    {
                        Class = new GradLin();
                        break;
                    }
                    case CLASS_TYPE_CHART_DATA:
                    {
                        Class = new asc_CChart();
                        break;
                    }
                    case CLASS_TYPE_CHART_LAYOUT:
                    {
                        Class = new CChartLayout();
                        break;
                    }
                }

                if(isRealObject(Class))
                {
                    Class.Id = Id;
                    this.m_aPairs[Id] = Class;
                }

                this.m_bTurnOff = false;
                break;
            }
        }
        // Ничего не делаем (можно удалять/добавлять ссылки на классы в данном классе
        // но это не обяательно, т.к. Id всегда уникальные)
    },
//-----------------------------------------------------------------------------------
// Функции для работы с совместным редактирования
//-----------------------------------------------------------------------------------
    Read_Class_FromBinary: function(Reader)
    {
        var ElementType = Reader.GetLong();
        var Element = null;

        // Временно отключаем регистрацию новых классов
        this.m_bTurnOff = true;

        switch( ElementType )
        {
            case historyitem_type_Paragraph        : Element = new Paragraph(); break;
            case historyitem_type_TextPr           : Element = new ParaTextPr(); break;
            case historyitem_type_Drawing          : Element = new ParaDrawing(); break;
            //case historyitem_type_DrawingObjects   : Element = new CDrawingObjects(); break;
            // case historyitem_type_FlowObjects      : Element = new FlowObjects(); break;
            case historyitem_type_FlowImage        : Element = new FlowImage(); break;
            case historyitem_type_Table            : Element = new CTable(); break;
            case historyitem_type_TableRow         : Element = new CTableRow(); break;
            case historyitem_type_TableCell        : Element = new CTableCell(); break;
            case historyitem_type_DocumentContent  : Element = new CDocumentContent(); break;
            case historyitem_type_FlowTable        : Element = new FlowTable(); break;
            case historyitem_type_HdrFtr           : Element = new CHeaderFooter(); break;
            case historyitem_type_AbstractNum      : Element = new CAbstractNum(); break;
        }

        Element.Read_FromBinary2(Reader);

        // Включаем назад регистрацию новых классов
        this.m_bTurnOff = false;

        return Element;
    },

    Save_Changes: function(Data, Writer)
    {
        // Сохраняем изменения из тех, которые используются для Undo/Redo в бинарный файл.
        // Long : тип класса
        // Long : тип изменений

        Writer.WriteLong( historyitem_type_TableId );

        var Type = Data.Type;

        // Пишем тип
        Writer.WriteLong( Type );
        switch ( Type )
        {
            case historyitem_TableId_Add :
            {
                // String   : Id элемента
                // Varibale : сам элемент

                Writer.WriteString2( Data.Id );
                Data.Class.Write_ToBinary2( Writer );

                break;
            }

            case historyitem_TableId_Reset:
            {
                // String : Id_new
                // String : Id_old

                Writer.WriteString2( Data.Id_new );
                Writer.WriteString2( Data.Id_old );

                break;
            }
        }
    },

    Save_Changes2: function(Data, Writer)
    {
        return false;
    },

    Load_Changes: function(Reader, Reader2)
    {
        // Сохраняем изменения из тех, которые используются для Undo/Redo в бинарный файл.
        // Long : тип класса
        // Long : тип изменений

        var ClassType = Reader.GetLong();
        if ( historyitem_type_TableId != ClassType )
            return;

        var Type = Reader.GetLong();

        switch ( Type )
        {
            case historyitem_TableId_Add:
            {
                // String   : Id элемента
                // Varibale : сам элемент

                var Id    = Reader.GetString2();
                var Class = this.Read_Class_FromBinary( Reader );

                this.m_aPairs[Id] = Class;

                break;
            }

            case historyitem_TableId_Reset:
            {
                // String : Id_new
                // String : Id_old

                var Id_new = Reader.GetString2();
                var Id_old = Reader.GetString2();

                if ( "undefined" != this.m_aPairs[Id_old] )
                {
                    var Class = this.m_aPairs[Id_old];
                    delete this.m_aPairs[Id_old];
                    this.m_aPairs[Id_new] = Class;
                }

                break;
            }

        }

        return true;
    },

    Unlock: function(Data)
    {
        // Ничего не делаем
    }
};

var g_oIdCounter = null;

var CLASS_TYPE_TABLE_ID = 0;
var CLASS_TYPE_DOCUMENT_CONTENT = 1;
var CLASS_TYPE_SHAPE = 2;
var CLASS_TYPE_IMAGE = 3;
var CLASS_TYPE_GROUP = 4;
var CLASS_TYPE_XFRM = 5;
var CLASS_TYPE_GEOMETRY = 6;
var CLASS_TYPE_PATH = 7;
var CLASS_TYPE_PARAGRAPH = 8;
var CLASS_TYPE_TEXT_BODY = 9;
var CLASS_TYPE_TEXT_PR = 10;
var CLASS_TYPE_UNI_FILL = 11;
var CLASS_TYPE_PATTERN_FILL = 12;
var CLASS_TYPE_GRAD_FILL = 13;
var CLASS_TYPE_SOLID_FILL = 14;
var CLASS_TYPE_UNI_COLOR = 15;
var CLASS_TYPE_SCHEME_COLOR = 16;
var CLASS_TYPE_RGB_COLOR = 17;
var CLASS_TYPE_PRST_COLOR = 18;
var CLASS_TYPE_SYS_COLOR = 19;
var CLASS_TYPE_LINE = 20;
var CLASS_TYPE_CHART_AS_GROUP = 21;
var CLASS_TYPE_CHART_LEGEND = 22;
var CLASS_TYPE_CHART_TITLE = 23;
var CLASS_TYPE_COLOR_MOD = 24;
var CLASS_TYPE_LEGEND_ENTRY = 25;
var CLASS_TYPE_CHART_DATA = 26;
var CLASS_TYPE_NO_FILL = 27;
var CLASS_TYPE_GS = 28;
var CLASS_TYPE_GRAD_LIN = 29;
var CLASS_TYPE_GRAD_PAT = 30;
var CLASS_TYPE_BLIP_FILL = 31;
var CLASS_TYPE_CHART_LAYOUT = 32;





var g_oTableId = null;