

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Xml.Serialization;

namespace BallotTemplates
{
    [XmlType("BallotTemplate", Namespace = "urn:scan-omr:template")]
    [XmlRoot("template", Namespace = "urn:scan-omr:template")]
    public class BallotTemplate : IdentifiedObject
    {
        private const string MaxVersion = "0.8.0.0";

        
        
        private BallotTemplatePageInside _inside = new BallotTemplatePageInside();

        private BallotTemplatePageOutside _outside = new BallotTemplatePageOutside();

        
        
        
        public BallotTemplate()
        {
            Version = MaxVersion;
            ScanThreshold = 120;
            Id = "SomeBallot";
        }

        
        
        
        [XmlAttribute("electionLevel")]
        public string ElectionLevel { get; set; }

        
        
        
        [XmlAttribute("version")]
        public string Version { get; set; }

        
        
        
        [XmlAttribute("DPI")]
        public int DPI { get; set; }

        
        
        
        [XmlAttribute("typeId")]
        public string TypeId { get; set; }

        
        
        
        [XmlAttribute("physicalWidthMm")]
        public float PhysicalWidthMm { get; set; }

        
        
        
        [XmlAttribute("physicalHeightMm")]
        public float PhysicalHeightMm { get; set; }

        
        
        
        [Browsable(false)]
        [XmlIgnore]
        public string FileName { get; set; }

        
        
        
        [XmlElement("inside")]
        [Description("The inside template")]
        public BallotTemplatePageInside Inside
        {
            get => _inside;
            set
            {
                _inside = value;
                OnPropertyChange(nameof(Inside));
            }
        }

        
        
        
        [XmlElement("outside")]
        [Description("The outside template")]
        public BallotTemplatePageOutside Outside
        {
            get => _outside;
            set
            {
                _outside = value;
                OnPropertyChange(nameof(Outside));
            }
        }

        public string Xml
        {
            get
            {
                using (var sw = new StringWriter())
                {
                    var xsz = new XmlSerializer(typeof(BallotTemplate));
                    xsz.Serialize(sw, this);
                    return xsz.ToString();
                }
            }
        }

        
        
        
        [XmlAttribute("scanThreshold")]
        public int ScanThreshold { get; set; }


        
        
        
        
        

        
        
        
        public void Save()
        {
            
            using (var fs = File.Create(FileName))
            {
                var xsz = new XmlSerializer(typeof(BallotTemplate));
                xsz.Serialize(fs, this);
            }
        }

        
        
        
        public static BallotTemplate Load(string fileName)
        {
            
            using (var fs = File.OpenRead(fileName))
            {
                var xsz = new XmlSerializer(typeof(BallotTemplate));
                var retVal = xsz.Deserialize(fs) as BallotTemplate;

                Debug.Assert(retVal != null, nameof(retVal) + " != null");
                if (new Version(retVal.Version) > new Version(MaxVersion))
                    throw new TemplateVersionException(retVal.Version, MaxVersion);

                retVal.FileName = fileName;
                return retVal;
            }
        }

        public static BallotTemplate LoadXml(string xml)
        {
            
            using (var sr = new StringReader(xml))
            
            {
                var xsz = new XmlSerializer(typeof(BallotTemplate));
                var retVal = xsz.Deserialize(sr) as BallotTemplate;
                if (retVal?.Version == null || new Version(retVal.Version) > new Version(MaxVersion))
                    throw new TemplateVersionException(retVal?.Version, MaxVersion);

                retVal.FileName = "";
                return retVal;
            }
        }
    }
}
