public void Write(Stream stream, DxfDocument document, bool binary)
        {
            this.doc = document;
            this.isBinary = binary;

            if (this.doc.DrawingVariables.AcadVer < DxfVersion.AutoCad2000)
                throw new NotSupportedException("Only AutoCad2000 and newer dxf versions are supported.");

            this.encodedStrings = new Dictionary<string, string>();

            // create the default PaperSpace layout in case it does not exist. The ModelSpace layout always exists
            if (this.doc.Layouts.Count == 1)
                this.doc.Layouts.Add(new Layout("Layout1"));

            // create the application registry AcCmTransparency in case it doesn't exists, it is required by the layer and entity transparency
            this.doc.ApplicationRegistries.Add(new ApplicationRegistry("AcCmTransparency"));

            // create the application registry GradientColor1ACI and GradientColor2ACI in case they don't exists , they are required by the hatch gradient pattern
            this.doc.ApplicationRegistries.Add(new ApplicationRegistry("GradientColor1ACI"));
            this.doc.ApplicationRegistries.Add(new ApplicationRegistry("GradientColor2ACI"));

            // dictionaries
            List<DictionaryObject> dictionaries = new List<DictionaryObject>();

            // Named dictionary it is always the first to appear in the object section
            DictionaryObject namedObjectDictionary = new DictionaryObject(this.doc);
            this.doc.NumHandles = namedObjectDictionary.AsignHandle(this.doc.NumHandles);
            dictionaries.Add(namedObjectDictionary);

            // create the Group dictionary, this dictionary always appear even if there are no groups in the drawing
            DictionaryObject groupDictionary = new DictionaryObject(namedObjectDictionary);
            this.doc.NumHandles = groupDictionary.AsignHandle(this.doc.NumHandles);
            foreach (Group group in this.doc.Groups.Items)
            {
                groupDictionary.Entries.Add(group.Handle, group.Name);
            }
            dictionaries.Add(groupDictionary);
            namedObjectDictionary.Entries.Add(groupDictionary.Handle, DxfObjectCode.GroupDictionary);

            // Layout dictionary
            DictionaryObject layoutDictionary = new DictionaryObject(namedObjectDictionary);
            this.doc.NumHandles = layoutDictionary.AsignHandle(this.doc.NumHandles);
            if (this.doc.Layouts.Count > 0)
            {
                foreach (Layout layout in this.doc.Layouts.Items)
                {
                    layoutDictionary.Entries.Add(layout.Handle, layout.Name);
                }
                dictionaries.Add(layoutDictionary);
                namedObjectDictionary.Entries.Add(layoutDictionary.Handle, DxfObjectCode.LayoutDictionary);
            }

            // create the Underlay definitions dictionary
            DictionaryObject dgnDefinitionDictionary = new DictionaryObject(namedObjectDictionary);
            this.doc.NumHandles = dgnDefinitionDictionary.AsignHandle(this.doc.NumHandles);
            if (this.doc.UnderlayDgnDefinitions.Count > 0)
            {
                foreach (UnderlayDgnDefinition underlayDef in this.doc.UnderlayDgnDefinitions.Items)
                {
                    dgnDefinitionDictionary.Entries.Add(underlayDef.Handle, underlayDef.Name);
                    dictionaries.Add(dgnDefinitionDictionary);
                    namedObjectDictionary.Entries.Add(dgnDefinitionDictionary.Handle, DxfObjectCode.UnderlayDgnDefinitionDictionary);
                }
            }
            DictionaryObject dwfDefinitionDictionary = new DictionaryObject(namedObjectDictionary);
            this.doc.NumHandles = dwfDefinitionDictionary.AsignHandle(this.doc.NumHandles);
            if (this.doc.UnderlayDwfDefinitions.Count > 0)
            {
                foreach (UnderlayDwfDefinition underlayDef in this.doc.UnderlayDwfDefinitions.Items)
                {
                    dwfDefinitionDictionary.Entries.Add(underlayDef.Handle, underlayDef.Name);
                    dictionaries.Add(dwfDefinitionDictionary);
                    namedObjectDictionary.Entries.Add(dwfDefinitionDictionary.Handle, DxfObjectCode.UnderlayDwfDefinitionDictionary);
                }
            }
            DictionaryObject pdfDefinitionDictionary = new DictionaryObject(namedObjectDictionary);
            this.doc.NumHandles = pdfDefinitionDictionary.AsignHandle(this.doc.NumHandles);
            if (this.doc.UnderlayPdfDefinitions.Count > 0)
            {
                foreach (UnderlayPdfDefinition underlayDef in this.doc.UnderlayPdfDefinitions.Items)
                {
                    pdfDefinitionDictionary.Entries.Add(underlayDef.Handle, underlayDef.Name);
                    dictionaries.Add(pdfDefinitionDictionary);
                    namedObjectDictionary.Entries.Add(pdfDefinitionDictionary.Handle, DxfObjectCode.UnderlayPdfDefinitionDictionary);
                }
            }

            // create the MLine style dictionary
            DictionaryObject mLineStyleDictionary = new DictionaryObject(namedObjectDictionary);
            this.doc.NumHandles = mLineStyleDictionary.AsignHandle(this.doc.NumHandles);
            if (this.doc.MlineStyles.Count > 0)
            {
                foreach (MLineStyle mLineStyle in this.doc.MlineStyles.Items)
                {
                    mLineStyleDictionary.Entries.Add(mLineStyle.Handle, mLineStyle.Name);
                }
                dictionaries.Add(mLineStyleDictionary);
                namedObjectDictionary.Entries.Add(mLineStyleDictionary.Handle, DxfObjectCode.MLineStyleDictionary);
            }

            // create the image dictionary
            DictionaryObject imageDefDictionary = new DictionaryObject(namedObjectDictionary);
            this.doc.NumHandles = imageDefDictionary.AsignHandle(this.doc.NumHandles);
            if (this.doc.ImageDefinitions.Count > 0)
            {
                foreach (ImageDefinition imageDef in this.doc.ImageDefinitions.Items)
                {
                    imageDefDictionary.Entries.Add(imageDef.Handle, imageDef.Name);
                }

                dictionaries.Add(imageDefDictionary);

                namedObjectDictionary.Entries.Add(imageDefDictionary.Handle, DxfObjectCode.ImageDefDictionary);
                namedObjectDictionary.Entries.Add(this.doc.RasterVariables.Handle, DxfObjectCode.ImageVarsDictionary);
            }

            this.doc.DrawingVariables.HandleSeed = this.doc.NumHandles.ToString("X");

            this.Open(stream, this.doc.DrawingVariables.AcadVer < DxfVersion.AutoCad2007 ? Encoding.Default : null);

            // The comment group, 999, is not used in binary DXF files.
            if (!this.isBinary)
            {
                foreach (string comment in this.doc.Comments)
                    this.WriteComment(comment);
            }

            //HEADER SECTION
            this.BeginSection(DxfObjectCode.HeaderSection);
            foreach (HeaderVariable variable in this.doc.DrawingVariables.Values)
            {
                this.WriteSystemVariable(variable);
            }
            // writing a copy of the active dimension style variables in the header section will avoid to be displayed as <style overrides> in AutoCad
            DimensionStyle activeDimStyle;
             if(this.doc.DimensionStyles.TryGetValue(this.doc.DrawingVariables.DimStyle, out activeDimStyle))
                 this.WriteActiveDimensionStyleSystemVaribles(activeDimStyle);
            this.EndSection();

            //CLASSES SECTION
            this.BeginSection(DxfObjectCode.ClassesSection);
            this.WriteRasterVariablesClass(1);
            if (this.doc.ImageDefinitions.Items.Count > 0)
            {
                this.WriteImageDefClass(this.doc.ImageDefinitions.Count);
                this.WriteImageDefRectorClass(this.doc.Images.Count);
                this.WriteImageClass(this.doc.Images.Count);
            }
            this.EndSection();

            //TABLES SECTION
            this.BeginSection(DxfObjectCode.TablesSection);

            //registered application tables
            this.BeginTable(this.doc.ApplicationRegistries.CodeName, (short) this.doc.ApplicationRegistries.Count, this.doc.ApplicationRegistries.Handle);
            foreach (ApplicationRegistry id in this.doc.ApplicationRegistries.Items)
            {
                this.WriteApplicationRegistry(id);
            }
            this.EndTable();

            //viewport tables
            this.BeginTable(this.doc.VPorts.CodeName, (short) this.doc.VPorts.Count, this.doc.VPorts.Handle);
            foreach (VPort vport in this.doc.VPorts)
            {
                this.WriteVPort(vport);
            }
            this.EndTable();

            //line type tables
            //The LTYPE table always precedes the LAYER table. I guess because the layers reference the line types,
            //why this same rule is not applied to DIMSTYLE tables is a mystery, since they also reference text styles and block records
            this.BeginTable(this.doc.LineTypes.CodeName, (short) this.doc.LineTypes.Count, this.doc.LineTypes.Handle);
            foreach (LineType lineType in this.doc.LineTypes.Items)
            {
                this.WriteLineType(lineType);
            }
            this.EndTable();

            //layer tables
            this.BeginTable(this.doc.Layers.CodeName, (short) this.doc.Layers.Count, this.doc.Layers.Handle);
            foreach (Layer layer in this.doc.Layers.Items)
            {
                this.WriteLayer(layer);
            }
            this.EndTable();

            //text style tables
            this.BeginTable(this.doc.TextStyles.CodeName, (short) this.doc.TextStyles.Count, this.doc.TextStyles.Handle);
            foreach (TextStyle style in this.doc.TextStyles.Items)
            {
                this.WriteTextStyle(style);
            }
            this.EndTable();

            //dimension style tables
            this.BeginTable(this.doc.DimensionStyles.CodeName, (short) this.doc.DimensionStyles.Count, this.doc.DimensionStyles.Handle);
            foreach (DimensionStyle style in this.doc.DimensionStyles.Items)
            {
                this.WriteDimensionStyle(style);
            }
            this.EndTable();

            //view
            this.BeginTable(this.doc.Views.CodeName, (short)this.doc.Views.Count, this.doc.Views.Handle);
            this.EndTable();

            //UCS
            this.BeginTable(this.doc.UCSs.CodeName, (short) this.doc.UCSs.Count, this.doc.UCSs.Handle);
            foreach (UCS ucs in this.doc.UCSs.Items)
            {
                this.WriteUCS(ucs);
            }
            this.EndTable();

            //block record table
            this.BeginTable(this.doc.Blocks.CodeName, (short) this.doc.Blocks.Count, this.doc.Blocks.Handle);
            foreach (Block block in this.doc.Blocks.Items)
            {
                this.WriteBlockRecord(block.Record);
            }
            this.EndTable();

            this.EndSection(); //End section tables

            //BLOCKS SECTION
            this.BeginSection(DxfObjectCode.BlocksSection);
            foreach (Block block in this.doc.Blocks.Items)
            {
                Layout layout = null;
                if (block.Name.StartsWith(Block.DefaultPaperSpaceName))
                {
                    // the entities of the layouts associated with the blocks "*Paper_Space0", "*Paper_Space1",... are included in the Blocks Section
                    string index = block.Name.Remove(0, 12);
                    if (!string.IsNullOrEmpty(index))
                    {
                        layout = block.Record.Layout;
                    }
                }
                this.WriteBlock(block, layout);
            }
            this.EndSection(); //End section blocks

            //ENTITIES SECTION
            this.BeginSection(DxfObjectCode.EntitiesSection);
            foreach (Layout layout in this.doc.Layouts)
            {
                if (!layout.IsPaperSpace) 
                {
                    // ModelSpace
                    List<DxfObject> entities = this.doc.Layouts.GetReferences(layout);
                    foreach (DxfObject o in entities)
                    {
                        this.WriteEntity(o as EntityObject, layout);
                    }
                }
                else if (layout.AssociatedBlock.Name.StartsWith(Block.DefaultPaperSpaceName))
                {
                    // only the entities of the layout associated with the block "*Paper_Space" are included in the Entities Section
                    string index = layout.AssociatedBlock.Name.Remove(0, 12);
                    if (string.IsNullOrEmpty(index))
                    {
                        this.WriteEntity(layout.Viewport, layout);
                        List<DxfObject> entities = this.doc.Layouts.GetReferences(layout);
                        foreach (DxfObject o in entities)
                        {
                            this.WriteEntity(o as EntityObject, layout);
                        }
                    }
                }
            }
            this.EndSection(); //End section entities

            //OBJECTS SECTION
            this.BeginSection(DxfObjectCode.ObjectsSection);

            foreach (DictionaryObject dictionary in dictionaries)
            {
                this.WriteDictionary(dictionary);
            }

            foreach (Group group in this.doc.Groups.Items)
            {
                this.WriteGroup(group, groupDictionary.Handle);
            }

            foreach (Layout layout in this.doc.Layouts)
            {
                this.WriteLayout(layout, layoutDictionary.Handle);
            }

            foreach (MLineStyle style in this.doc.MlineStyles.Items)
            {
                this.WriteMLineStyle(style, mLineStyleDictionary.Handle);
            }

            foreach (UnderlayDgnDefinition underlayDef in this.doc.UnderlayDgnDefinitions.Items)
            {
                this.WriteUnderlayDefinition(underlayDef, dgnDefinitionDictionary.Handle);
            }
            foreach (UnderlayDwfDefinition underlayDef in this.doc.UnderlayDwfDefinitions.Items)
            {
                this.WriteUnderlayDefinition(underlayDef, dwfDefinitionDictionary.Handle);
            }
            foreach (UnderlayPdfDefinition underlayDef in this.doc.UnderlayPdfDefinitions.Items)
            {
                this.WriteUnderlayDefinition(underlayDef, pdfDefinitionDictionary.Handle);
            }

            // the raster variables dictionary is only needed when the drawing has image entities
            if (this.doc.ImageDefinitions.Count > 0)
            {
                this.WriteRasterVariables(this.doc.RasterVariables, imageDefDictionary.Handle);
                foreach (ImageDefinition imageDef in this.doc.ImageDefinitions.Items)
                {
                    foreach (ImageDefinitionReactor reactor in imageDef.Reactors.Values)
                    {
                        this.WriteImageDefReactor(reactor);
                    }
                    this.WriteImageDef(imageDef, imageDefDictionary.Handle);
                }
            }
                
            this.EndSection(); //End section objects

            this.Close();

            stream.Position = 0;
        }