#include <siadriveconfig.h>
#include <fstream>
#include <filepath.h>
#include <siacommon.h>
#if defined(_WIN32) && !defined(_DEBUG)
#include <ShlObj.h>
#endif
using namespace Sia::Api;

CSiaDriveConfig::CSiaDriveConfig(const bool& autoSave) :
	CSiaDriveConfig(autoSave, SString(DEFAULT_CONFIG_FILE_PATH))
{
}

CSiaDriveConfig::CSiaDriveConfig(const bool& autoSave, const SString& filePath) :
  _autoSave(autoSave),
  _FilePath(FilePath(filePath).Resolve())
{
  Load();
}

CSiaDriveConfig::CSiaDriveConfig(const json& configDoc) :
  _autoSave(false),
  _configDocument(configDoc)
{
}

CSiaDriveConfig::~CSiaDriveConfig()
{
  if (_autoSave)
  {
    Save();
  }
}

void CSiaDriveConfig::OnAutoStartOnLogonChanged(const bool& value)
{
#if defined(_WIN32) && !defined(_DEBUG)
  ComInitWrapper cw;

  PWSTR startupPath = nullptr;
  if (SUCCEEDED(::SHGetKnownFolderPath(FOLDERID_Startup, 0, nullptr, &startupPath)))
  {
    FilePath shortcutPath(startupPath, "SiaDrive.lnk");
    
    const BOOL exists = ::PathFileExists(&shortcutPath[0]); 
    if (exists)
    {
      ::DeleteFile(&shortcutPath[0]);
    }

    if (value)
    {
      SString execPath;
      execPath.Resize(MAX_PATH + 1);
      GetModuleFileName(::GetModuleHandle(nullptr), &execPath[0], MAX_PATH);
      execPath.Fit();
      CreateShortcut(execPath, "SiaDrive", shortcutPath, true);
    }
     
    ::CoTaskMemFree(startupPath);
  }
#endif 
#if !defined(_WIN32)
  a
#endif
}

bool CSiaDriveConfig::LoadDefaults()
{
  bool changed = false;
  if (!CheckRenter_UploadDbFilePath())
  {
    SetRenter_UploadDbFilePath(static_cast<SString>(FilePath(DEFAULT_RENTER_DB_FILE_PATH).Resolve()));
    changed = true;
  }

  if (!CheckTempFolder())
  {
    FilePath tempFolder = FilePath::GetTempDirectory();
    SetTempFolder(static_cast<SString>(tempFolder));
    changed = true;
  }

  if (!CheckCacheFolder())
  {
    FilePath cacheFolder(FilePath::GetAppDataDirectory(), "siadrive");
    cacheFolder.Append("cache");
    SetCacheFolder(static_cast<SString>(cacheFolder));
    changed = true;
  }

  if (!CheckHostNameOrIp())
  {
    SetHostNameOrIp("localhost");
    changed = true;
  }

  if (!CheckApiPort())
  {
#ifdef _WIN32
    SetApiPort(GetRegistry("ApiPort", 9980));
#else
    SetApiPort(9980);
#endif
    changed = true;
  }

  if (!CheckHostPort())
  {
#ifdef _WIN32
    SetHostPort(GetRegistry("HostPort", 9982));
#else
    SetHostPort(9982);
#endif
    changed = true;
  }

  if (!CheckRpcPort())
  {
#ifdef _WIN32
    SetRpcPort(GetRegistry("RpcPort", 9981));
#else
    SetRpcPort(9981);
#endif
    changed = true;
  }

  if (!CheckMaxUploadCount())
  {
    SetMaxUploadCount(20);
    changed = true;
  }

  if (!CheckLockWalletOnExit())
  {
    SetLockWalletOnExit(false);
    changed = true;
  }

  if (!CheckAutoStartOnLogon())
  {
    SetAutoStartOnLogon(false);
    changed = true;
  }

  if (!CheckLaunchBundledSiad())
  {
    SetLaunchBundledSiad(true);
    changed = true;
  }

  if (!CheckEventLevel())
  {
#ifdef _DEBUG
    SetEventLevel("Debug");
#else
    SetEventLevel("Normal");
#endif
    changed = true;
  }

  if (!CheckLaunchFileMgrOnMount())
  {
    SetLaunchFileMgrOnMount(true);
    changed = true;
  }
  
  if (!CheckCloseToTray())
  {
    SetCloseToTray(true);
    changed = true;
  }

  if (!CheckStoreUnlockPassword())
  {
    SetStoreUnlockPassword(false);
    changed = true;
  }

  if (!CheckAutoMountOnUnlock())
  {
    SetAutoMountOnUnlock(false);
    changed = true;
  }

  if (!CheckLastMountLocation())
  {
    SetLastMountLocation("");
    changed = true;
  }

  if (!CheckConfirmApplicationExit())
  {
    SetConfirmApplicationExit(false);
    changed = true;
  }

  return changed;
}

void CSiaDriveConfig::Load( )
{
  FilePath filePath = GetFilePath();
	std::ifstream myfile(static_cast<SString>(filePath).str().c_str());
	if (myfile.is_open())
	{
		std::stringstream ss;
		ss << myfile.rdbuf();
		std::string jsonTxt = ss.str();
		_configDocument = json::parse(jsonTxt.begin(), jsonTxt.end());
		myfile.close();
	}
	
	if (LoadDefaults())
  {
		Save();
	}

  // Do this to add/remove shortcut on start-up
  OnAutoStartOnLogonChanged(GetAutoStartOnLogon());

  FilePath cacheFolder(GetCacheFolder());
  if (!cacheFolder.IsDirectory())
  {
    cacheFolder.CreateDirectory();
  }
}

void CSiaDriveConfig::Save() const
{
	FilePath filePath = GetFilePath();
  FilePath folder = filePath;
  folder.RemoveFileName();

	if (!folder.IsDirectory())
	{
    folder.CreateDirectory();
	}
	std::ofstream(SString::ToUtf8(static_cast<SString>(filePath)).c_str()) << std::setw(2) << _configDocument << std::endl;
}

SString CSiaDriveConfig::ToString() const
{
  return _configDocument.dump();
}

SiaHostConfig CSiaDriveConfig::GetHostConfig() const
{
  SiaHostConfig hostConfig;
  hostConfig.HostName = GetHostNameOrIp();
  hostConfig.HostPort = GetApiPort();
  hostConfig.RequiredVersion = COMPAT_SIAD_VERSION;
  return hostConfig;
}
