using Google.Protobuf;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Hosting;
using System.Web.Http;
using Tango.BL;
using Tango.BL.Builders;
using Tango.BL.Entities;
using Tango.Core.DB;
using Tango.Core.Helpers;
using Tango.Core.IO;
using Tango.Logging;
using Tango.MachineService.Models;
using Tango.PMR.Stubs;
using Tango.PMR.Synchronization;
using Tango.Synchronization.Local;
using Tango.Synchronization.Remote;
namespace Tango.MachineService.Controllers
{
public class SynchronizationController : ApiController
{
private LogManager logManager = LogManager.Default;
///
/// Expects a DB synchronization request from a remote machine and returns the synchronized version of the machine database.
///
/// The request.
///
[HttpPost]
public SynchronizeDBResponse Synchronize(SynchronizeDBRequest request)
{
var tempFolder = TemporaryManager.Default.CreateFolder();
try
{
//File path for the reflected remote data base SQLite.
String masterSQLiteFile = Path.Combine(tempFolder, "Remote.db");
//File path for the received machine SQLite db.
String slaveSQLiteFile = Path.Combine(tempFolder, "Local.db");
//Save the machine db to file.
File.WriteAllBytes(slaveSQLiteFile, request.LocalDB.ToByteArray());
//Copy an SQLite db template.
File.Copy(HostingEnvironment.MapPath(@"~/App_Data/Tango.db"), masterSQLiteFile);
//Synchronize the SQL Server db with the new SQLite template. (Overwrite basically)
RemoteDBSynchronizer.Synchronize(masterSQLiteFile, request.SerialNumber, true);
//Synchronize the received machine db with the filled template.
LocalDBSynchronizer.Synchronize(masterSQLiteFile, slaveSQLiteFile);
//Send the synchronized machine db to the machine to the machine.
SynchronizeDBResponse response = new SynchronizeDBResponse();
response.RemoteDB = ByteString.CopyFrom(File.ReadAllBytes(slaveSQLiteFile));
return response;
}
catch (Exception)
{
throw;
}
finally
{
//Remove all temporary files and folder.
tempFolder.Delete();
}
}
[HttpPost]
public MachineSetupResponse MachineSetup(MachineSetupRequest request)
{
MachineSetupResponse response = new MachineSetupResponse();
logManager.Log("Setup request received: " + request.ToString());
try
{
using (ObservablesContext db = ObservablesContext.CreateDefault(GetLocalServerAddress()))
{
db.Configuration.LazyLoadingEnabled = false;
String serial_number = request.SerialNumber;
var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == serial_number);
if (machine == null)
{
ThrowError(HttpStatusCode.NotFound, "The specified serial number could not be found.");
}
var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == machine.MachineVersionGuid);
var latest_machine_version = db.TangoVersions.Where(x => x.MachineVersionGuid == machine_version.Guid).ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault();
response.Version = latest_machine_version.Version;
response.FtpAddress = GetFtpAddress();
response.FtpFilePath = latest_machine_version.FtpFilePath;
response.FtpUserName = GetFtpUserName();
response.FtpPassword = GetFtpPassword();
DbCredentials credentials = new DbCredentials();
using (DbManager manager = DbManager.FromAddressAndName(GetDbAddress(), "Tango"))
{
credentials = manager.CreateRandomLoginAndUser("Tango");
Task.Delay(TimeSpan.FromMinutes(10)).ContinueWith((x) =>
{
using (DbManager m = DbManager.FromAddressAndName(GetDbAddress(), "Tango"))
{
m.DeleteLoginAndUser(credentials.UserName, "Tango");
}
});
}
response.DbAddress = GetDbAddress();
response.DbUserName = credentials.UserName;
response.DbPassword = credentials.Password;
}
}
catch (Exception ex)
{
logManager.Log(ex);
throw;
}
return response;
}
[HttpPost]
public DownloadUpdateResponse MachineUpdate(DownloadUpdateRequest request)
{
DownloadUpdateResponse response = new DownloadUpdateResponse();
try
{
using (ObservablesContext db = ObservablesContext.CreateDefault(GetLocalServerAddress()))
{
db.Configuration.LazyLoadingEnabled = false;
String serial_number = request.SerialNumber;
var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == serial_number);
if (machine == null)
{
OnError(HttpStatusCode.NotFound, "The specified serial number could not be found.");
}
var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == machine.MachineVersionGuid);
var latest_machine_version = db.TangoVersions.Where(x => x.MachineVersionGuid == machine_version.Guid).ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault();
response.Version = latest_machine_version.Version;
response.FtpAddress = GetFtpAddress();
response.FtpFilePath = latest_machine_version.FtpFilePath;
response.FtpUserName = GetFtpUserName();
response.FtpPassword = GetFtpPassword();
DbCredentials credentials = new DbCredentials();
using (DbManager manager = DbManager.FromAddressAndName(GetDbAddress(), "Tango"))
{
credentials = manager.CreateRandomLoginAndUser("Tango");
Task.Delay(TimeSpan.FromMinutes(10)).ContinueWith((x) =>
{
using (DbManager m = DbManager.FromAddressAndName(GetDbAddress(), "Tango"))
{
m.DeleteLoginAndUser(credentials.UserName, "Tango");
}
});
}
response.DbAddress = GetDbAddress();
response.DbUserName = credentials.UserName;
response.DbPassword = credentials.Password;
}
}
catch (Exception ex)
{
OnError(HttpStatusCode.InternalServerError, ex.Message);
}
return response;
}
[HttpPost]
public CheckForUpdateResponse CheckForUpdate(CheckForUpdateRequest request)
{
CheckForUpdateResponse response = new CheckForUpdateResponse();
try
{
using (ObservablesContext db = ObservablesContext.CreateDefault(GetLocalServerAddress()))
{
db.Configuration.LazyLoadingEnabled = false;
var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == request.SerialNumber);
if (machine == null)
{
OnError(HttpStatusCode.NotFound, "The specified serial number could not be found.");
}
var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == machine.MachineVersionGuid);
var latest_machine_version = db.TangoVersions.Where(x => x.MachineVersionGuid == machine_version.Guid).ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault();
if (Version.Parse(latest_machine_version.Version) > Version.Parse(request.Version))
{
response.IsUpdateAvailable = true;
}
response.Version = latest_machine_version.Version;
}
}
catch (Exception ex)
{
OnError(HttpStatusCode.InternalServerError, ex.Message);
}
return response;
}
[HttpPost]
public UpdateDBResponse UpdateDB(UpdateDBRequest request)
{
UpdateDBResponse response = new UpdateDBResponse();
try
{
using (ObservablesContext db = ObservablesContext.CreateDefault(GetLocalServerAddress()))
{
db.Configuration.LazyLoadingEnabled = false;
String serial_number = request.SerialNumber;
var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == serial_number);
if (machine == null)
{
OnError(HttpStatusCode.NotFound, "The specified serial number could not be found.");
}
DbCredentials credentials = new DbCredentials();
using (DbManager manager = DbManager.FromAddressAndName(GetDbAddress(), "Tango"))
{
credentials = manager.CreateRandomLoginAndUser("Tango");
Task.Delay(TimeSpan.FromMinutes(10)).ContinueWith((x) =>
{
using (DbManager m = DbManager.FromAddressAndName(GetDbAddress(), "Tango"))
{
m.DeleteLoginAndUser(credentials.UserName, "Tango");
}
});
}
response.DbAddress = GetDbAddress();
response.DbUserName = credentials.UserName;
response.DbPassword = credentials.Password;
}
}
catch (Exception ex)
{
OnError(HttpStatusCode.InternalServerError, ex.Message);
}
return response;
}
[HttpPost]
public Machine PersonTest(Person p)
{
using (var db = ObservablesContext.CreateDefault(GetLocalServerAddress()))
{
var machine = new MachineBuilder(db)
.Set(x => x.SerialNumber == "1111")
.WithOrganization()
.WithConfiguration().Build();
return machine;
}
}
#region Helpers
private void ThrowError(HttpStatusCode code, String message)
{
throw new WebApiException(code, message);
}
private void OnError(HttpStatusCode code, String message)
{
throw new HttpResponseException(Request.CreateErrorResponse(code, message));
}
private String GetLocalServerAddress()
{
return ConfigurationManager.AppSettings["LocalServerAddress"].ToString();
}
private String GetDbAddress()
{
return ConfigurationManager.AppSettings["DbAddress"].ToString();
}
private String GetFtpAddress()
{
return ConfigurationManager.AppSettings["FtpAddress"].ToString();
}
private String GetFtpUserName()
{
return ConfigurationManager.AppSettings["FtpUserName"].ToString();
}
private String GetFtpPassword()
{
return ConfigurationManager.AppSettings["FtpPassword"].ToString();
}
#endregion
}
}