#include "ads_pluginloader.h"

//#include "ads_driver1553.h"

#include "avb_driver.h"

//#include <QPluginLoader>
#include <QLibrary>

#include <QFileInfo>
#include <QDir>
#include <QMessageBox>
#include <QCoreApplication>
#include <QFileDialog>
#include <QDebug>

#include <QHostAddress>
#include <QSettings>

//Q_IMPORT_PLUGIN(adsDriver1553DdcSim)
//Q_IMPORT_PLUGIN(DummyDriver1553)
class IAvbDriver;

//Ads_driver1553* AdsDriver1553_DummyDriver();

#if 0
static Ads_driver1553* tryLoad(const QString& /*driver_name*/, int /*x=0*/) //QPluginLoader& ploader)
{
  QPluginLoader& ploader;
  bool loaded=false;
  if (false)
  {
      QFileInfo fname(driver_name);
      QString fixed_name=driver_name;
      QDir pluginsDir = QDir(QCoreApplication::applicationDirPath());
      QString dir_name=pluginsDir.dirName();
      bool is_develop=(dir_name.toLower()) == "debug" || (dir_name == "release");

      if (is_develop)
      {
        pluginsDir.cd("../..");
        pluginsDir.cd(fname.completeBaseName());
        pluginsDir.cd(dir_name);
        fixed_name=pluginsDir.absoluteFilePath(fname.fileName());
      }
      if (fname.suffix()!="dll")
      {
        fixed_name+=".dll";
      }
      ploader.setFileName(pluginsDir.absoluteFilePath(fixed_name));
      loaded=ploader.load();
      if (!loaded)
        return 0;

      Ads_driver1553* d=qobject_cast<Ads_driver1553*>(ploader.instance());
      return d;
  }
  else
  {
      Ads_driver1553* d=AdsDriver1553_DummyDriver();
      return d;
  }
  Ads_driver1553* d=AdsDriver1553_DummyDriver();
  return d;
}
#endif

class AvbClientConcrete: public IAvbDriverClient
{
public:
    virtual void logError(const char* fmt, ...)
    {
        va_list args;
        va_start(args, fmt);
        qWarning()<<QString::vasprintf(fmt, args);
        va_end(args);
    }

    virtual bool getSettingsBool(const char* name)
    {
        return false;
    }

    virtual int getSettingsInt(const char* name)
    {
        return 0;
    }
};

static IAvbDriver* tryLoad(const QString& driver_name__, int /*x=0*/) //QPluginLoader& ploader)
{
    static AvbClientConcrete avbClientConcrete;
  bool loaded=false;

  QString driver_name=driver_name__;

  if (driver_name.startsWith('?'))
  {
      driver_name=driver_name.remove(0, 1);

      int r=QMessageBox::question(0, "Avd Load", "Load driver "+driver_name, QMessageBox::Yes, QMessageBox::No);
      if (r!=QMessageBox::Yes)
          return 0;
  }

  {
      QFileInfo fname(driver_name);
      QString fixed_name=driver_name;

      QLibrary ploader(fixed_name);
      bool ok=ploader.load();

      if (!ok)
      {
          QMessageBox::warning(0, "Avd Load", QString("Load FAILED: %1").arg(ploader.errorString()));
          qWarning()<<"AvbLoad:"<<"Load FAILED -"<<ploader.errorString();
          return 0;
      }

      qDebug()<<"AvbLoad: loaded"<<ploader.fileName();

      AvbDriverCreator_function_t qgp_create=(AvbDriverCreator_function_t)ploader.resolve(AVBDRIVER_CREATOR_FUNCTION_NAME);
      if (!qgp_create)
      {
          QMessageBox::warning(0, "Avb Loader", QString("FAIL: Cannot resolve: %1").arg(ploader.errorString()));
          qWarning()<<"AvbLoader:"<<"FAIL: Cannot resolve -"<<ploader.errorString();
          return 0;
      }

      IAvbDriver* d=qgp_create("", &avbClientConcrete);
      if (d==0)
          return 0;
      return d;
  }
}

AdsPluginLoader::AdsPluginLoader()
{
}

extern IAvbDriver* RexAvdDriveCreate(const QHostAddress* ha);

IAvbDriver* AdsPluginLoader::loadAvbDriver(const QString& requested_name, QSettings *settings)
{
    //return tryLoad(requested_name)->createDriver(settings);
    //return RexAvdDriveCreate();

    QString driver_name=requested_name;

    QString ovr_ha=settings->value("SystemConfig/udp1553_network", QString()).toString();
    QHostAddress ha;
    QHostAddress* pha=0;
    if (!ovr_ha.isEmpty())
    {
        ovr_ha.remove(QChar('"'));
        ha=QHostAddress(ovr_ha);
        qDebug()<<"****udp1553_network="<<ovr_ha<<ha;
        pha=&ha;
    }
    if (driver_name.isEmpty())
    {
        return RexAvdDriveCreate(pha);
    }

    IAvbDriver* d=tryLoad(requested_name, 0);
    if (d==0)
        return RexAvdDriveCreate(pha);
    else
        return d;
#if 0
  QString driver_name=requested_name;

  if (driver_name.isEmpty())
  {
      return RexAvdDriveCreate();
  }
  QPluginLoader ploader;

  bool avb_simulator=(driver_name.isNull() || driver_name.isEmpty() || driver_name==QString("<simulator>"));

  Ads_driver1553* obj=0;

  if (!avb_simulator)
  {
    for(;obj==0;)
    {
      obj=tryLoad(driver_name, ploader);
      if (!obj)
      {
        QMessageBox::StandardButton res=QMessageBox::information(0,
           "1553 Driver load error",
           QString("%1\n\nDo you want to retry with the simulator?").arg(ploader.errorString()),
           QMessageBox::Yes|QMessageBox::Abort|QMessageBox::Retry);
         if (res==QMessageBox::Retry)
         {
           QString fileName = QFileDialog::getOpenFileName(0, "Open 1553 driver", QString(), "Driver file (*.dll)");
           if (!fileName.isNull() && !fileName.isEmpty())
             driver_name=fileName;
         }
         else if (res==QMessageBox::Yes)
           break;
         else
           return 0;
      }
      qDebug()<<"DRIVER1553: loaded "<<ploader.fileName();
    }
  }

  //Simulator
  if (obj==0 || !ploader.isLoaded())
  {
    //obj=tryLoad("ads_driver1553_ddc_sim.dll", ploader);
    QObjectList pl=QPluginLoader::staticInstances();
    foreach(QObject* o, pl)
    {
      obj=qobject_cast<Ads_driver1553*>(o);
      if (obj)
      {
        qDebug()<<"DRIVER1553: using built-in simulator";
        break;
      }
    }
  }

  if (!obj)
  {
    QMessageBox::critical(0, "1553 Driver load error", ploader.errorString());
    return 0;
  }
  IAvbDriver* d=obj->createDriver(settings);
  return d;
#endif
}

