﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.ServiceModel;
using Raspberry.IO.GeneralPurpose;
using Raspberry.IO.InterIntegratedCircuit;

using Talos.Common;

namespace Talos
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
    class TalosIO: ITalosIO, IDisposable
    {
        I2cDriver driver;
        Waveshare10DofImuSensor accelerometer;
        Dictionary<int,ProcessorPin> gpioPins;

        public IEnumerable<Type> Dependencies { get; } = new Type[] { typeof(IConfig), typeof(ILog) };
        public bool IsSingletone { get; } = true;

        public TalosIO()
        {
            try
            {
                Log.Info("Initializing Talos I/O");
                if (!Raspberry.Board.Current.IsRaspberryPi)
                    throw new TalosException("The Talos server can run only on Raspberry Pi.");

                gpioPins = Config.Enumerate<int>("gpio-pins")
                    .ToDictionary(p => p, p => ((ConnectorPin)Enum.Parse(typeof(ConnectorPin), "P1Pin" + p)).ToProcessor());
                if (!gpioPins.ContainsKey(3) || !gpioPins.ContainsKey(3))
                    throw new TalosException("Pins 3 and 5 are required for the I²C interface.");
                driver = new I2cDriver(gpioPins[3], gpioPins[5]);
                accelerometer = new Waveshare10DofImuSensor(driver);
            }
            catch (Exception e)
            {
                throw TalosServiceFault.FaultException(e, "Cannot initialize service.");
            }

        }

        public double Pressure
        {
            get
            {
                try
                {
                    double pressure = double.NaN;
                    Log.Debug("Requested temperature, {0:0} Pa", pressure);
                    return pressure;
                }
                catch (Exception e)
                {
                    Log.Error(e);
                    throw TalosServiceFault.FaultException(e);
                }
            }
        }

        public double CpuTemperature
        {
            get
            {
                try
                {
                    string text = File.ReadAllText("/sys/class/thermal/thermal_zone0/temp");
                    double temp = double.Parse(text) / 1000;    

                    Log.Debug("Requested temperature, {0:0.0}°C", temp);
                    return temp;
                }
                catch (Exception e)
                {
                    Log.Error(e);
                    throw TalosServiceFault.FaultException(e);
                }
            }
        }

        public VectorContract Acceleration
        {
            get
            {
                try
                {
                    return accelerometer.Acceleration;
                }
                catch (Exception e)
                {
                    Log.Error(e);
                    throw TalosServiceFault.FaultException(e);
                }
            }
        }

        public VectorContract AngularAcceleration
        {
            get
            {
                try
                {
                    return accelerometer.AngularAcceleration;
                }
                catch (Exception e)
                {
                    Log.Error(e);
                    throw TalosServiceFault.FaultException(e);
                }
            }
        }

        public void Dispose()
        {
            accelerometer?.Dispose();
            driver?.Dispose();
            Log.Info("Talos I/O shut down.");
        }
    }
}
