using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using CsvHelper;
using CsvHelper.Configuration;
using MileageTraker.Web.Models;
using MileageTraker.Web.Utility;

namespace MileageTraker.Web.DAL
{
	public static class FuelmanCsvImporter
    {
		private sealed class FuelmanCsvClassMap : CsvClassMap<FuelLog>
		{
			readonly string[] _dateFormats = { @"M/d/yy HH:mm", @"M/d/yyyy HH:mm" };
			public FuelmanCsvClassMap()
			{
				Map(m => m.Date).ConvertUsing(row =>
					{
						var date = row.GetField("CEDATE");
						var time = row.GetField<int>("CETIME");
						var dttm = string.Format(@"{0} {1:00:00}", date, time);

						DateTime parsed;
						if (DateTime.TryParseExact(dttm, _dateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out parsed))
							return parsed;

						throw new ArgumentException(string.Format("Date in incorrect format: CEDATE:{0} CETIME:{1}", date, time));
					});
				Map(m => m.DriverFullName).ConvertUsing(row =>
					{
						var name = row.GetField("CEEMNAME");
						return NameNormalizer.Normalize(name);
					});

				Map(m => m.TagNumber).Name("CEVEHNO");
				Map(m => m.Odometer).Name("CEODOMETER");
				Map(m => m.CityName).ConvertUsing(row =>
					{
						var city = row.GetField("CESITCTY");
						return city.ToLower().ToTitleCase();
					});
				Map(m => m.MPG).Name("CEMPG");
				Map(m => m.GasPurchased).Name("CEQTY");
				Map(m => m.TotalPrice).Name("CECUSAMT");
			}
		}

		public static bool IsProbablyTabSeparated(FileInfo fileInfo)
		{
			using (var tr = File.OpenText(fileInfo.FullName))
			{
				var line = tr.ReadLine();
				var tabHeadCount = 
					(from c in line
					 where c == '\t'
					 select c).Count();
				// if there's more than 10 tabs in the first line, probably TSV
				return tabHeadCount > 10;
			}
		}

		public static ICollection<FuelLog> Import(FileInfo fileInfo)
		{
			if (!fileInfo.Exists)
				throw new ImportException("Cannot find file '" + fileInfo.Name + "'");

			var tabSeparatedValues = IsProbablyTabSeparated(fileInfo);

			using (var tr = File.OpenText(fileInfo.FullName))
			{
				var csvConfiguration = new CsvConfiguration();
				if (tabSeparatedValues)
					csvConfiguration.Delimiter = "\t";
				csvConfiguration.RegisterClassMap<FuelmanCsvClassMap>();

				var csv = new CsvReader(tr, csvConfiguration);

				var fuelLogs = new List<FuelLog>();
				while (csv.Read())
				{
					try
					{
						// Skip non-FUEL entries
						if (csv.GetField<string>("CEPRDTYPE") != "FUEL")
							continue;

						fuelLogs.Add(csv.GetRecord<FuelLog>());
					}
					catch (Exception ex)
					{
						throw new ImportException("Problem with document encountered on row " + csv.Row + ". " + ex.Message);
					}
				}

				return fuelLogs;
			}
		}
    }
}
