/* 
 * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#ifndef _WF_Utilities_H_
#define _WF_Utilities_H_

using namespace System;
using namespace System::Windows::Forms;
using namespace System::Runtime::InteropServices;

namespace MySQL {
  namespace Forms {

    // Message type for the C# interface.
    public enum class MessageType
    {
      MessageInfo,
      MessageWarning,
      MessageError
    };

    /**
     * A custom message box for the output as there is no predefined dialog which allows to
     * have custom button captions.
     */
    public ref class CustomMessageBox : Form
    {
    private:
      // Constructor is private. CustomMessageBox should be accessed through the public Show() method
      CustomMessageBox();

      // GUI Elements, we have 3 buttons whose text can be customized.
      Label^ _messageLabel;
      Button^ _button1;
      Button^ _button2;
      Button^ _button3;
      PictureBox^ _picture;
      CheckBox^ _checkbox;

      void ComputeLayout();
      void ButtonClick(System::Object^ sender, EventArgs^ e);

      static mforms::DialogResult ShowVistaStyle(const std::string& title, const std::string& text,
        PCWSTR mainIcon, const std::string& buttonOK, const std::string& buttonCancel,
        const std::string& buttonOther, const std::string& checkbox, bool& checked);

      static mforms::DialogResult ShowTraditionalStyle(String^ title,  String^ text, System::Drawing::Image^ image,
         String^ button1,  String^ button2,  String^ button3,  String^ checkbox, bool& checked);
    public:
      // C++ interface
      static mforms::DialogResult Show(const std::string& title, const std::string& text,
        PCWSTR mainIcon, const std::string& buttonOK, const std::string& buttonCancel,
        const std::string& buttonOther, const std::string& checkbox, bool& checked);

      // C# interface
      static Windows::Forms::DialogResult Show(MessageType type,  String^ title,  String^ text,  String^ buttonOK,
         String^ buttonCancel,  String^ buttonOther,  String^ checkbox, [Out] bool% checked);
      static Windows::Forms::DialogResult Show(MessageType type,  String^ title,  String^ text,  String^ buttonOK);
    };

    private ref class InvokationResult
    {
    private:
      void* _result;
    public:
      InvokationResult(void* result)
      {
        _result = result;
      }

      property void* Result
      {
        void* get()
        {
          return _result;
        }
      };
    };

    private ref class DispatchControl : Control
    {
    private:
      boost::function<void* ()> *_slot;
      InvokationResult^ RunSlot();
    public:
      ~DispatchControl();
      void* RunOnMainThread(const boost::function<void* ()>& slot, bool wait);
    };

    public ref class UtilitiesImpl
    {
    private:
      static DispatchControl^ _dispatcher;

      static void load_passwords();
      static void unload_passwords(bool store);
    protected:
      UtilitiesImpl();

      static int show_message(const std::string &title, const std::string &text, const std::string &ok, 
        const std::string &cancel, const std::string &other);
      static int show_error(const std::string &title, const std::string &text, const std::string &ok, 
        const std::string &cancel, const std::string &other);
      static int show_warning(const std::string &title, const std::string &text, const std::string &ok, 
        const std::string &cancel, const std::string &other);
      static int show_message_with_checkbox(const std::string &title, const std::string &text, const std::string &ok, 
        const std::string &cancel, const std::string &other, const std::string &checkbox_text, bool &isChecked);
      static void show_wait_message(const std::string &title, const std::string &text);
      static bool hide_wait_message();
      static bool run_cancelable_wait_message(const std::string &title, const std::string &text, 
        const boost::function<void ()> &start_task, const boost::function<bool ()> &cancel_slot);
      static void stop_cancelable_wait_message();

      static void set_clipboard_text(const std::string &content);
      static std::string get_clipboard_text();
      static std::string get_special_folder(mforms::FolderType type);

      static void open_url(const std::string &url);
      static bool move_to_trash(const std::string &file_name);
      static void reveal_file(const std::string &path);

      static void add_timeout(float interval, const boost::function<bool ()> &slot);

      static void store_password(const std::string &service, const std::string &account, const std::string &password);
      static bool find_password(const std::string &service, const std::string &account, std::string &password);
      static void forget_password(const std::string &service, const std::string &account);

      static void* perform_from_main_thread(const boost::function<void* ()> &slot, bool wait);
    public:
      static Windows::Forms::Form^ get_mainform();

      static void init(Manager ^mgr)
      {
        _dispatcher = gcnew DispatchControl();
        _dispatcher->Handle; // create window handle

        mforms::ControlFactory *f= mforms::ControlFactory::get_instance();

        DEF_CALLBACK5(int, const std::string&, const std::string&, const std::string&, const std::string&, const std::string&, 
          mgr, f->_utilities_impl, UtilitiesImpl, show_message);
        DEF_CALLBACK5(int, const std::string&, const std::string&, const std::string&, const std::string&, const std::string&, 
          mgr, f->_utilities_impl, UtilitiesImpl, show_error);
        DEF_CALLBACK5(int, const std::string&, const std::string&, const std::string&, const std::string&, const std::string&, 
          mgr, f->_utilities_impl, UtilitiesImpl, show_warning);
        DEF_CALLBACK7(int, const std::string&, const std::string&, const std::string&, const std::string&, const std::string&, 
          const std::string&, bool&, mgr, f->_utilities_impl, UtilitiesImpl, show_message_with_checkbox);
        DEF_CALLBACK2(void, const std::string&, const std::string&, mgr, f->_utilities_impl, UtilitiesImpl,
          show_wait_message);
        DEF_CALLBACK0(bool, mgr, f->_utilities_impl, UtilitiesImpl, hide_wait_message);
        DEF_CALLBACK4(bool, const std::string&, const std::string&, const boost::function<void ()> &, const boost::function<bool ()>&, mgr, f->_utilities_impl, UtilitiesImpl, run_cancelable_wait_message);
        DEF_CALLBACK0(void, mgr, f->_utilities_impl, UtilitiesImpl, stop_cancelable_wait_message);
        DEF_CALLBACK1(void, const std::string&, mgr, f->_utilities_impl, UtilitiesImpl, set_clipboard_text);
        DEF_CALLBACK0(std::string, mgr, f->_utilities_impl, UtilitiesImpl, get_clipboard_text);
        DEF_CALLBACK1(void, const std::string&, mgr, f->_utilities_impl, UtilitiesImpl, open_url);
        DEF_CALLBACK1(bool, const std::string&, mgr, f->_utilities_impl, UtilitiesImpl, move_to_trash);
        DEF_CALLBACK2(void, float, const boost::function<bool ()>&, mgr, f->_utilities_impl, UtilitiesImpl, add_timeout);
        DEF_CALLBACK1(std::string, mforms::FolderType, mgr, f->_utilities_impl, UtilitiesImpl, get_special_folder);
        DEF_CALLBACK3(void, const std::string&, const std::string&, const std::string&, mgr, f->_utilities_impl, UtilitiesImpl, store_password);
        DEF_CALLBACK3(bool, const std::string&, const std::string&, std::string&, mgr, f->_utilities_impl, UtilitiesImpl, find_password);
        DEF_CALLBACK2(void, const std::string&, const std::string&, mgr, f->_utilities_impl, UtilitiesImpl, forget_password);
        DEF_CALLBACK2(void*, const boost::function<void* ()>&, bool, mgr, f->_utilities_impl, UtilitiesImpl, perform_from_main_thread);
        DEF_CALLBACK1(void, const std::string&, mgr, f->_utilities_impl, UtilitiesImpl, reveal_file);
      }
    };
  };
};

#endif // _WF_Utilities_H_
