/*
 * Copyright 2011 NEHTA
 *
 * Licensed under the NEHTA Open Source (Apache) License; you may not use this
 * file except in compliance with the License. A copy of the License is in the
 * 'license.txt' file, which should be provided with this work.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

using System.Collections.Generic;
using Nehta.VendorLibrary.CDA.Common;
using Nehta.VendorLibrary.CDA.Generator.Enums;
using Nehta.VendorLibrary.Common;

namespace Nehta.VendorLibrary.CDA.SCSModel.Common
{
    /// <summary>
    /// Interval.
    /// Allowable combinations: Low, Width, High, Center, Low/High, Low/Width, High/Width, Center/Width
    /// </summary>
    public class CdaInterval
    {
        /// <summary>
        /// Type of interval.
        /// </summary>
        public IntervalType Type { get; private set; }

        /// <summary>
        /// Low value.
        /// </summary>
        public ISO8601DateTime Low { get; private set; }

        /// <summary>
        /// Center value.
        /// </summary>
        public ISO8601DateTime Center { get; private set; }

        /// <summary>
        /// High value.
        /// </summary>
        public ISO8601DateTime High { get; private set; }

        /// <summary>
        /// Interval width.
        /// </summary>
        public CdaIntervalWidth IntervalWidth { get; private set; }


        /// <summary>
        /// Constructor.
        /// </summary>
        private CdaInterval()
        {            
        }

        /// <summary>
        /// Creates an interval with low.
        /// </summary>
        /// <param name="low">Low.</param>
        /// <returns>Interval</returns>
        public static CdaInterval CreateLow(ISO8601DateTime low)
        {            
            Validation.ValidateArgumentRequired("low", low);

            return new CdaInterval
                       {
                           Type = IntervalType.Low,
                           Low = low
                       };
        }

        /// <summary>
        /// Creates an interval with a width.
        /// </summary>
        /// <param name="value">Value</param>
        /// <param name="unit">Unit</param>
        /// <returns>Interval.</returns>
        public static CdaInterval CreateWidth(string value, TimeUnitOfMeasure unit)
        {
            Validation.ValidateArgumentRequired("value", value);
            Validation.ValidateArgumentRequired("unit", unit);

            return new CdaInterval
                       {
                           Type = IntervalType.Width,
                           IntervalWidth = new CdaIntervalWidth(value, unit)
                       };
        }

        /// <summary>
        /// Creates an interval with high.
        /// </summary>
        /// <param name="high">Low.</param>
        /// <returns>Interval</returns>
        public static CdaInterval CreateHigh(ISO8601DateTime high)
        {
            Validation.ValidateArgumentRequired("high", high);

            return new CdaInterval
                       {
                           Type = IntervalType.High,
                           High = high
                       };
        }

        /// <summary>
        /// Creates an interval with center.
        /// </summary>
        /// <param name="center">Center.</param>
        /// <returns>Interval</returns>
        public static CdaInterval CreateCenter(ISO8601DateTime center)
        {
            Validation.ValidateArgumentRequired("center", center);

            return new CdaInterval
                       {
                           Type = IntervalType.Center,
                           Center = center
                       };
        }

        /// <summary>
        /// Creates an interval with high and low.
        /// </summary>
        /// <param name="low">Low.</param>
        /// <param name="high">High.</param>
        /// <returns>Interval.</returns>
        public static CdaInterval CreateLowHigh(ISO8601DateTime low, ISO8601DateTime high)
        {
            Validation.ValidateArgumentRequired("low", low);
            Validation.ValidateArgumentRequired("high", high);

            return new CdaInterval
                       {
                           Type = IntervalType.LowHigh,
                           Low = low, 
                           High = high
                       };
        }

        /// <summary>
        /// Creates an interval with low and width.
        /// </summary>
        /// <param name="low">Low.</param>
        /// <param name="value">Value.</param>
        /// <param name="unit">Unit.</param>
        /// <returns>Interval</returns>
        public static CdaInterval CreateLowWidth(ISO8601DateTime low, string value, TimeUnitOfMeasure unit)
        {
            Validation.ValidateArgumentRequired("low", low);
            Validation.ValidateArgumentRequired("value", value);
            Validation.ValidateArgumentRequired("unit", unit);

            return new CdaInterval
                       {
                           Type = IntervalType.LowWidth,
                           Low = low, 
                           IntervalWidth = new CdaIntervalWidth(value, unit)
                       };
        }

        /// <summary>
        /// Creates an interval with high and width.
        /// </summary>
        /// <param name="high">High.</param>
        /// <param name="value">Value.</param>
        /// <param name="unit">Unit.</param>
        /// <returns>Interval</returns>
        public static CdaInterval CreateHighWidth(ISO8601DateTime high, string value, TimeUnitOfMeasure unit)
        {
            Validation.ValidateArgumentRequired("high", high);
            Validation.ValidateArgumentRequired("value", value);
            Validation.ValidateArgumentRequired("unit", unit);

            return new CdaInterval
                       {
                           Type = IntervalType.HighWidth,
                           High = high, 
                           IntervalWidth = new CdaIntervalWidth(value, unit)
                       };
        }

        /// <summary>
        /// Creates an interval with center and width.
        /// </summary>
        /// <param name="center">Center.</param>
        /// <param name="value">Value.</param>
        /// <param name="unit">Unit.</param>
        /// <returns>Interval</returns>
        public static CdaInterval CreateCenterWidth(ISO8601DateTime center, string value, TimeUnitOfMeasure unit)
        {
            Validation.ValidateArgumentRequired("center", center);
            Validation.ValidateArgumentRequired("value", value);
            Validation.ValidateArgumentRequired("unit", unit);

            return new CdaInterval
                       {
                           Type = IntervalType.CenterWidth,
                           Center = center, 
                           IntervalWidth = new CdaIntervalWidth(value, unit)
                       };
        }

        /// <summary>
        /// Validates the interval.
        /// </summary>
        /// <param name="path">The path to this object as a string</param>
        /// <param name="messages">the validation messages to date, these may be added to within this method</param>
        public void Validate(string path, List<ValidationMessage> messages)
        {
            // No validation is required as only a valid interval can be created and the
            // properties are not settable.
        }

        /// <summary>
        /// Type of the interval.
        /// </summary>
        public enum IntervalType
        {
            /// <summary>
            /// Low
            /// </summary>
            Low,

            /// <summary>
            /// Low width
            /// </summary>
            LowWidth,

            /// <summary>
            /// Low high
            /// </summary>
            LowHigh,

            /// <summary>
            /// High
            /// </summary>
            High,

            /// <summary>
            /// High width
            /// </summary>
            HighWidth,

            /// <summary>
            /// Center
            /// </summary>
            Center,

            /// <summary>
            /// Center width
            /// </summary>
            CenterWidth,

            /// <summary>
            /// Width
            /// </summary>
            Width,
        }

    }
}


