//  MapAround - .NET tools for developing web and desktop mapping applications 

//  Copyright (coffee) 2009-2012 OOO "GKR"
//  This program is free software; you can redistribute it and/or 
//  modify it under the terms of the GNU General Public License 
//   as published by the Free Software Foundation; either version 3 
//  of the License, or (at your option) any later version. 
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program; If not, see <http://www.gnu.org/licenses/>



/*===========================================================================
** 
** File: MultiLineHandler.cs 
** 
** Copyright (c) Complex Solution Group. 
**
** Description: Handling linear objects of the Shape-file
**
=============================================================================*/

namespace MapAround.IO.Handlers
{
    using System;
    using System.IO;

    using MapAround.Geometry;
    using MapAround.IO;

    /// <summary>
    /// Îáðàáîò÷èê äëÿ ôèãóðû "Ëîìàíàÿ ëèíèÿ"
    /// </summary>
    internal class MultiLineHandler : ShapeHandler
    {
        /// <summary> Òèï ôèãóðû</summary>
        public override ShapeType ShapeType
        {
            get { return ShapeType.Polyline; }
        }

        /// <summary>
        /// ×èòàåò çàïèñü ïðåäñòàâëÿþùóþ ïîëèãîí.
        /// </summary>
        /// <param name="file">Âõîäíîé ïîòîê</param>
        /// <param name="record">Çàïèñü Shape-ôàéëà â êîòîðóþ áóäåò ïîìåùåíà ïðî÷èòàííàÿ èíôîðìàöèÿ</param>
        /// <param name="bounds">Îãðàíè÷èâàþùèé ïðÿìîóãîëüíèê, ñ êîòîðûì äîëæåí ïåðåñåêàòüñÿ îãðàíè÷èâàþùèé ïðÿìîóãîëüíèê çàïèñè</param>
        /// <returns>Óñïåøíîñòü îïåðàöèè</returns>
        public override bool Read(Stream file, BoundingRectangle bounds, ShapeFileRecord record)
        {
            record.MinX = file.ReadDouble();// ShapeFile.ReadDouble64_LE(stream);
            record.MinY = file.ReadDouble(); //ShapeFile.ReadDouble64_LE(stream);
            record.MaxX = file.ReadDouble();// ShapeFile.ReadDouble64_LE(stream);
            record.MaxY = file.ReadDouble();// ShapeFile.ReadDouble64_LE(stream);

            int numParts = file.ReadInt32();// ShapeFile.ReadInt32_LE(stream);
            int numPoints = file.ReadInt32(); //ShapeFile.ReadInt32_LE(stream);

            if (!ShapeHandler.IsRecordInView(bounds, record))
            {
                file.Seek((long)numPoints * 16 + numParts * 4, SeekOrigin.Current);
                return false;
            }

            for (int i = 0; i < numParts; i++)
                record.Parts.Add(file.ReadInt32());//ShapeFile.ReadInt32_LE(stream));

            for (int i = 0; i < numPoints; i++)
            {
                ICoordinate p =
                    PlanimetryEnvironment.NewCoordinate(
                        file.ReadDouble(),//ShapeFile.ReadDouble64_LE(stream),
                        file.ReadDouble());//ShapeFile.ReadDouble64_LE(stream));

                record.Points.Add(p);
            }

            return true;
        }



        /// <summary>
        /// Çàïèñûâàåò äàííûå ëîìàíîé ëèíèè â óêàçàííûé ïîòîê. 
        ///</summary>
        /// <param name="geometry">îáúåêò ëîìàíîé ëèíèè äëÿ çàïèñè</param>
        /// <param name="file">Ïîòîê çàïèñè</param>        
        public override void Write(IGeometry geometry, BinaryWriter file)//, IGeometryFactory geometryFactory)
        {
            Polyline multi = (Polyline)geometry;

            file.Write(int.Parse(Enum.Format(typeof(ShapeType), ShapeType, "d")));

            BoundingRectangle box = multi.GetBoundingRectangle();
            file.Write(box.MinX);
            file.Write(box.MinY);
            file.Write(box.MaxX);
            file.Write(box.MaxY);

            int numParts = multi.Paths.Count;
            int numPoints = multi.CoordinateCount;

            file.Write(numParts);
            file.Write(numPoints);

            // Write the offsets
            int offset = 0;
            for (int i = 0; i < numParts; i++)
            {
                IGeometry g = multi.Paths[i];
                file.Write(offset);
                offset = offset + g.CoordinateCount;
            }

            ICoordinate[] points = multi.ExtractCoordinates();
            for (int i = 0; i < numPoints; i++)
            {
                file.Write(points[i].X);
                file.Write(points[i].Y);
            }           
        }


        /// <summary>
        /// Ïîëó÷èòü äëèíó ëîìàíîé ëèíèè â áàéòàõ (äëÿ çàïèñè â ôàéë)
        /// </summary>
        /// <param name="geometry">îáúåêò ëîìàíîé ëèíèè</param>
        /// <returns>
        /// Äëèíà äëÿ 16áèòîâîãî ôîðìàòà </returns>
        public override int GetLength(IGeometry geometry)
        {
            int numParts = ((Polyline)geometry).Paths.Count;// GetNumParts(geometry);
            return (22 + (2 * numParts) + geometry.CoordinateCount/*.NumPoints*/ * 8); // 22 => shapetype(2) + bbox(4*4) + numparts(2) + numpoints(2)
        }
        
    }
}