//****************************************************************************
//
// Copyright (c) ALTAP, spol. s r.o. All rights reserved.
//
// This is a part of the Altap Salamander SDK library.
//
// The SDK is provided "AS IS" and without warranty of any kind and 
// ALTAP EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS AND IMPLIED, INCLUDING,
// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE and NON-INFRINGEMENT.
//
//****************************************************************************

#include "precomp.h"

// objekt interfacu pluginu, jeho metody se volaji ze Salamandera
CPluginInterface PluginInterface;
// dalsi casti interfacu CPluginInterface
CPluginInterfaceForViewer InterfaceForViewer;
CPluginInterfaceForMenuExt InterfaceForMenuExt;
CPluginInterfaceForThumbLoader InterfaceForThumbLoader;

// globalni data
const char *PluginNameEN = "DemoView";          // neprekladane jmeno pluginu, pouziti pred loadem jazykoveho modulu + pro debug veci
const char *PluginNameShort = "DEMOVIEW";       // jmeno pluginu (kratce, bez mezer)

BOOL CfgSavePosition = FALSE;             // ukladat pozici okna/umistit dle hlavniho okna
WINDOWPLACEMENT CfgWindowPlacement = {0}; // neplatne, pokud CfgSavePosition != TRUE

DWORD LastCfgPage = 0;   // start page (sheet) in configuration dialog

const char *CONFIG_SAVEPOS = "SavePosition";
const char *CONFIG_WNDPLACEMENT = "WindowPlacement";

// ConfigVersion: 0 - zadna konfigurace se z Registry nenacetla (jde o instalaci pluginu),
//                1 - prvni verze konfigurace

int ConfigVersion = 0;            // verze nactene konfigurace z registry (popis verzi viz vyse)
#define CURRENT_CONFIG_VERSION 1  // aktualni verze konfigurace (uklada se do registry pri unloadu pluginu)
const char *CONFIG_VERSION = "Version";

HINSTANCE DLLInstance = NULL;       // handle k SPL-ku - jazykove nezavisle resourcy
HINSTANCE HLanguage = NULL;         // handle k SLG-cku - jazykove zavisle resourcy

// obecne rozhrani Salamandera - platne od startu az do ukonceni pluginu
CSalamanderGeneralAbstract *SalamanderGeneral = NULL;

// definice promenne pro "dbg.h"
CSalamanderDebugAbstract *SalamanderDebug = NULL;

// definice promenne pro "spl_com.h"
int SalamanderVersion = 0;

// rozhrani poskytujici upravene Windows controly pouzivane v Salamanderovi
CSalamanderGUIAbstract *SalamanderGUI = NULL;

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
  if (fdwReason == DLL_PROCESS_ATTACH)
  {
    DLLInstance = hinstDLL;

    INITCOMMONCONTROLSEX initCtrls;
    initCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
    initCtrls.dwICC = ICC_BAR_CLASSES;
    if (!InitCommonControlsEx(&initCtrls))
    {
      MessageBox(NULL, "InitCommonControlsEx failed!", "Error", MB_OK | MB_ICONERROR);
      return FALSE;  // DLL won't start
    }
  }

  return TRUE;    // DLL can be loaded
}

// ****************************************************************************

char *LoadStr(int resID)
{
  return SalamanderGeneral->LoadStr(HLanguage, resID);
}

void
OnConfiguration(HWND hParent)
{
  static BOOL InConfiguration = FALSE;
  if (InConfiguration)
  {
    SalamanderGeneral->SalMessageBox(hParent, LoadStr(IDS_CFG_ALREADY_OPENED), LoadStr(IDS_PLUGINNAME),
                                     MB_ICONINFORMATION | MB_OK);
    return;
  }
  InConfiguration = TRUE;
  if (CConfigDialog(hParent).Execute() == IDOK)
  {
    ViewerWindowQueue.BroadcastMessage(WM_USER_VIEWERCFGCHNG, 0, 0);
  }
  InConfiguration = FALSE;
}

void OnAbout(HWND hParent)
{
  char buf[1000];
  _snprintf_s(buf, _TRUNCATE, 
              "%s " VERSINFO_VERSION "\n\n"
              VERSINFO_COPYRIGHT "\n\n"
              "%s",
              LoadStr(IDS_PLUGINNAME),
              LoadStr(IDS_PLUGIN_DESCRIPTION));
  SalamanderGeneral->SalMessageBox(hParent, buf, LoadStr(IDS_ABOUT), MB_OK | MB_ICONINFORMATION);
}

//
// ****************************************************************************
// SalamanderPluginGetReqVer
//

#ifdef __BORLANDC__
extern "C"{
int WINAPI SalamanderPluginGetReqVer();
CPluginInterfaceAbstract * WINAPI SalamanderPluginEntry(CSalamanderPluginEntryAbstract *salamander);
};
#endif // __BORLANDC__

int WINAPI SalamanderPluginGetReqVer()
{
  return LAST_VERSION_OF_SALAMANDER;
}

//
// ****************************************************************************
// SalamanderPluginEntry
//

CPluginInterfaceAbstract * WINAPI SalamanderPluginEntry(CSalamanderPluginEntryAbstract *salamander)
{
  // nastavime SalamanderDebug pro "dbg.h"
  SalamanderDebug = salamander->GetSalamanderDebug();
  // nastavime SalamanderVersion pro "spl_com.h"
  SalamanderVersion = salamander->GetVersion();
  HANDLES_CAN_USE_TRACE();
  CALL_STACK_MESSAGE1("SalamanderPluginEntry()");

  // tento plugin je delany pro aktualni verzi Salamandera a vyssi - provedeme kontrolu
  if (SalamanderVersion < LAST_VERSION_OF_SALAMANDER)
  {  // starsi verze odmitneme
    MessageBox(salamander->GetParentWindow(),
               REQUIRE_LAST_VERSION_OF_SALAMANDER,
               PluginNameEN, MB_OK | MB_ICONERROR);
    return NULL;
  }

  // nechame nacist jazykovy modul (.slg)
  HLanguage = salamander->LoadLanguageModule(salamander->GetParentWindow(), PluginNameEN);
  if (HLanguage == NULL) return NULL;

  // ziskame obecne rozhrani Salamandera
  SalamanderGeneral = salamander->GetSalamanderGeneral();
  // ziskame rozhrani poskytujici upravene Windows controly pouzivane v Salamanderovi
  SalamanderGUI = salamander->GetSalamanderGUI();

  // nastavime jmeno souboru s helpem
  SalamanderGeneral->SetHelpFileName("demoview.chm");

  if (!InitViewer()) return NULL;  // chyba

  // nastavime zakladni informace o pluginu
  salamander->SetBasicPluginData(LoadStr(IDS_PLUGINNAME),
                                 FUNCTION_CONFIGURATION | FUNCTION_LOADSAVECONFIGURATION | FUNCTION_VIEWER,
                                 VERSINFO_VERSION_NO_PLATFORM, VERSINFO_COPYRIGHT, LoadStr(IDS_PLUGIN_DESCRIPTION),
                                 PluginNameShort, NULL, NULL);

  // nastavime URL home-page pluginu
  salamander->SetPluginHomePageURL(LoadStr(IDS_PLUGIN_HOME));

  // test SetPluginBugReportInfo
  SalamanderGeneral->SetPluginBugReportInfo(LoadStr(IDS_PLUGIN_BUGREP), LoadStr(IDS_PLUGIN_EMAIL));

  return &PluginInterface;
}

//
// ****************************************************************************
// CPluginInterface
//

void WINAPI
CPluginInterface::About(HWND parent)
{
  OnAbout(parent);
}

BOOL WINAPI
CPluginInterface::Release(HWND parent, BOOL force)
{
  CALL_STACK_MESSAGE2("CPluginInterface::Release(, %d)", force);
  BOOL ret = ViewerWindowQueue.Empty();
  if (!ret && (force || SalamanderGeneral->SalMessageBox(parent, LoadStr(IDS_VIEWER_OPENWNDS),
                                                         LoadStr(IDS_PLUGINNAME),
                                                         MB_YESNO | MB_ICONQUESTION) == IDYES))
  {
    ret = ViewerWindowQueue.CloseAllWindows(force) || force;
  }
  if (ret)
  {
    if (!ThreadQueue.KillAll(force) && !force) ret = FALSE;
    else ReleaseViewer();
  }
  return ret;
}

void WINAPI
CPluginInterface::LoadConfiguration(HWND parent, HKEY regKey, CSalamanderRegistryAbstract *registry)
{
  CALL_STACK_MESSAGE1("CPluginInterface::LoadConfiguration(, ,)");

  if (regKey != NULL)   // load z registry
  {
    if (!registry->GetValue(regKey, CONFIG_VERSION, REG_DWORD, &ConfigVersion, sizeof(DWORD)))
      ConfigVersion = CURRENT_CONFIG_VERSION;  // asi nejakej nenechavec... ;-)

    registry->GetValue(regKey, CONFIG_SAVEPOS, REG_DWORD, &CfgSavePosition, sizeof(DWORD));
    registry->GetValue(regKey, CONFIG_WNDPLACEMENT, REG_BINARY, &CfgWindowPlacement, sizeof(WINDOWPLACEMENT));
  }
}

void WINAPI
CPluginInterface::SaveConfiguration(HWND parent, HKEY regKey, CSalamanderRegistryAbstract *registry)
{
  CALL_STACK_MESSAGE1("CPluginInterface::SaveConfiguration(, ,)");

  DWORD v = CURRENT_CONFIG_VERSION;
  registry->SetValue(regKey, CONFIG_VERSION, REG_DWORD, &v, sizeof(DWORD));

  registry->SetValue(regKey, CONFIG_SAVEPOS, REG_DWORD, &CfgSavePosition, sizeof(DWORD));
  registry->SetValue(regKey, CONFIG_WNDPLACEMENT, REG_BINARY, &CfgWindowPlacement, sizeof(WINDOWPLACEMENT));
}

void WINAPI
CPluginInterface::Configuration(HWND parent)
{
  CALL_STACK_MESSAGE1("CPluginInterface::Configuration()");
  OnConfiguration(parent);
}

void WINAPI
CPluginInterface::Connect(HWND parent, CSalamanderConnectAbstract *salamander)
{
  CALL_STACK_MESSAGE1("CPluginInterface::Connect(,)");

  // zakladni cast:
  salamander->AddViewer("*.dmv", FALSE);

  salamander->AddMenuItem(-1, "&View Bitmap from Clipboard", SALHOTKEY('T', HOTKEYF_CONTROL | HOTKEYF_SHIFT),
                          MENUCMD_VIEWBMPFROMCLIP, FALSE, MENU_EVENT_TRUE, MENU_EVENT_TRUE, MENU_SKILLLEVEL_ALL);

  HBITMAP hBmp = (HBITMAP)HANDLES(LoadImage(DLLInstance, MAKEINTRESOURCE(IDB_PLUGINICO),
                                  IMAGE_BITMAP, 16, 16, LR_DEFAULTCOLOR));
  salamander->SetBitmapWithIcons(hBmp);
  HANDLES(DeleteObject(hBmp));
  salamander->SetPluginIcon(0);
  salamander->SetPluginMenuAndToolbarIcon(0);

  salamander->SetThumbnailLoader("*.bmv");  // poskytujeme thumbnaily pro .bmv soubory
}

void WINAPI
CPluginInterface::ClearHistory(HWND parent)
{
  ViewerWindowQueue.BroadcastMessage(WM_USER_CLEARHISTORY, 0, 0);
}

void CPluginInterface::Event(int event, DWORD param)
{
  switch (event) {
     case PLUGINEVENT_SETTINGCHANGE:
       ViewerWindowQueue.BroadcastMessage(WM_USER_SETTINGCHANGE, 0, 0);
       break;
  }
}

CPluginInterfaceForViewerAbstract * WINAPI
CPluginInterface::GetInterfaceForViewer()
{
  return &InterfaceForViewer;
}

CPluginInterfaceForMenuExtAbstract * WINAPI
CPluginInterface::GetInterfaceForMenuExt()
{
  return &InterfaceForMenuExt;
}

CPluginInterfaceForThumbLoaderAbstract * WINAPI
CPluginInterface::GetInterfaceForThumbLoader()
{
  return &InterfaceForThumbLoader;
}
