#include "handler.h"

Handler::Handler()
{
  this->_connect = NULL;
}

Handler::~Handler()
{
}

bool Handler::connect(const std::string &uri, std::string &err)
{
  virErrorPtr   errPtr;

  if ((this->_connect = virConnectOpen(uri.c_str())) == NULL) {
    errPtr = virGetLastError();
    err = "Failed to open connection to " + uri + ": " + std::string(errPtr->message);
    return (false);
  }
  return (true);
}

bool Handler::disconnect(std::string &err)
{
  virErrorPtr   errPtr;

  if (virConnectClose(this->_connect) < 0) {
    errPtr = virGetLastError();
    err = "Failed to disconnect: " + std::string(errPtr->message);
    return (false);
  }
  this->_connect = NULL;
  return (true);
}

bool Handler::startByName(const std::string &name, std::string &err)
{
  virErrorPtr   errPtr;
  virDomainPtr  domainPtr;

  if ((domainPtr = virDomainLookupByName(this->_connect, name.c_str())) == NULL) {
    errPtr = virGetLastError();
    err = "Cannot lookup for domain " + name + ": " + errPtr->message;
    return (false);
  }
  if (virDomainCreate(domainPtr) < 0) {
    errPtr = virGetLastError();
    err = "Cannot start domain " + name + ": " + errPtr->message;
    virDomainFree(domainPtr);
    return (false);
  }
  virDomainFree(domainPtr);
  return (true);
}

bool Handler::shutdownByName(const std::string &name, std::string &err)
{
  virErrorPtr   errPtr;
  virDomainPtr  domainPtr;

  if ((domainPtr = virDomainLookupByName(this->_connect, name.c_str())) == NULL) {
    errPtr = virGetLastError();
    err = "Cannot lookup for domain " + name + ": " + errPtr->message;
    return (false);
  }
  if (virDomainShutdown(domainPtr) < 0) {
    errPtr = virGetLastError();
    err = "Cannot shutdown domain " + name + ": " + errPtr->message;
    virDomainFree(domainPtr);
    return (false);
  }
  virDomainFree(domainPtr);
  return (true);
}

bool Handler::deleteByName(const std::string &name, std::string &err)
{
  virErrorPtr   errPtr;
  virDomainPtr  domainPtr;

  if ((domainPtr = virDomainLookupByName(this->_connect, name.c_str())) == NULL) {
    errPtr = virGetLastError();
    err = "Cannot lookup for domain " + name + ": " + errPtr->message;
    return (false);
  }
  if (virDomainUndefineFlags(domainPtr, VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
      VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA | VIR_DOMAIN_UNDEFINE_NVRAM) < 0) {
    errPtr = virGetLastError();
    err = "Cannot delete domain " + name + ": " + errPtr->message;
    virDomainFree(domainPtr);
    return (false);
  }
  virDomainFree(domainPtr);
  return (true);
}

bool Handler::getAllDomains(std::vector<Domain> &list, std::string &err)
{
  int i;
  int size;
  unsigned int domainId;
  virErrorPtr   errPtr;
  virDomainPtr *domains;

  if ((size = virConnectListAllDomains(this->_connect, &domains, 0)) < 0) {
    errPtr = virGetLastError();
    err = "Cannot get all domains list: " + std::string(errPtr->message);
    return (false);
  }
  list.resize(size);
  for (i = 0; i < size; i++) {
    if ((domainId = virDomainGetID(domains[i])) != (unsigned int) -1)
      list[i].setId(domainId);
    list[i].setName(virDomainGetName(domains[i]));
    virDomainGetInfo(domains[i], list[i].getDomainInfo());
    virDomainFree(domains[i]);
  }
  free(domains);
  return (true);
}

bool Handler::getDomainByName(Domain &domain, const std::string &name, std::string &err)
{
  virErrorPtr   errPtr;
  virDomainPtr  domainPtr;
  unsigned int  domainId;

  if ((domainPtr = virDomainLookupByName(this->_connect, name.c_str())) == NULL) {
    errPtr = virGetLastError();
    err = "Cannot lookup for domain " + name + ": " + errPtr->message;
    return (false);
  }
  if ((domainId = virDomainGetID(domainPtr)) != (unsigned int) -1)
    domain.setId(domainId);
  domain.setName(virDomainGetName(domainPtr));
  virDomainGetInfo(domainPtr, domain.getDomainInfo());
  virDomainFree(domainPtr);
  return (true);
}