/* 
 * Copyright (c) 2007, 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 _WIZARDFORM_H_
#define _WIZARDFORM_H_

#include <vector>
#include <set>

#include <grtpp.h>
#include "grt/common.h"

#include "wbpublic_public_interface.h"
#include "base/string_utilities.h"

#include "mforms/wizard.h"
#include "mforms/box.h"
#include "mforms/filechooser.h"

namespace bec {
  class GRTManager;
};

namespace mforms {
  class TextEntry;
};

namespace grtui {

  class WizardPage;

  class WBPUBLICBACKEND_PUBLIC_FUNC WizardForm : public ::mforms::Wizard
  {
  public:
    WizardForm(bec::GRTManager *mgr);
    virtual ~WizardForm();

    virtual bool run_modal();

    void add_page(WizardPage *page);

    void update_buttons();
    void update_heading();

    void set_problem(const std::string &text);
    void clear_problem();

    virtual void reset();
    
    void switch_to_page(WizardPage *page, bool advancing);
    WizardPage *get_active_page() { return _active_page; }
    int get_active_page_number();
    
    WizardPage *get_page_with_id(const std::string &id);

    bec::GRTManager *grtm() { return _grtm; }
    
    grt::DictRef values() { return _values; }
    
  public:
    // util stuff for storing state
    void set_wizard_option(const std::string &key, const std::string &value);
    std::string string_wizard_option(const std::string &key, const std::string &default_value= "");

    void set_wizard_option(const std::string &key, int value);
    int int_wizard_option(const std::string &key, int default_value= 0);

  private:    
    grt::DictRef _values;
     
    std::string _problem;

    WizardPage *_active_page;
    std::vector<WizardPage*> _pages;
    std::list<WizardPage*> _turned_pages;

    bool _cancelled;
  protected:
    bec::GRTManager *_grtm;

    virtual WizardPage *get_next_page(WizardPage *current);
    void refresh_step_list();

    void extra_clicked();
    
  public:
    void go_to_next();
    void go_to_back();
    void finish();
    virtual bool cancel();
  };


  /** A page of a wizard.
    */
  class WBPUBLICBACKEND_PUBLIC_FUNC WizardPage : public ::mforms::Box
  {
  public:
    WizardPage(WizardForm *form, const std::string &pageid);

    std::string get_id() const { return _id; }
    
    std::string get_title() const { return _title; }
    std::string get_short_title() const { return _short_title; }
    
    void set_title(const std::string &title);
    void set_short_title(const std::string &title);

    void validate();

    boost::signals2::signal<void (bool)>* signal_enter() { return &_signal_enter; }
    boost::signals2::signal<void (bool)>* signal_leave() { return &_signal_leave; }
    
  public:


  protected:
    friend class WizardForm;

    WizardForm *wizard() { return _form; }

    grt::DictRef values() { return _form->values(); }

    //! Subclasses must override this to implement validation.
    //! If there is a validation error, it must call _form->set_problem()
    virtual void do_validate() { }
    
    virtual int load() { return -1; } // delme XXX
    
    virtual bool pre_load();
    virtual void enter(bool advancing);
    virtual bool advance();
    virtual void leave(bool advancing);
    
    virtual bool allow_next() { return true; }
    virtual bool allow_back() { return true; }
    virtual bool allow_cancel() { return true; }
    virtual bool skip_page() { return false; } // Return true if the page should not be displayed (due to some condition).
    
    //! return true if this is the last page and pressing next should close wizard
    virtual bool next_closes_wizard() { return false; }
    
    //! overrider may return "" for default caption
    virtual std::string next_button_caption() { return ""; }
    
    virtual std::string extra_button_caption() { return ""; }

    std::string finish_button_caption() const
    {
#ifdef __APPLE__
      return _("Close");
#elif defined(_WIN32)
      return _("Finish");
#else
      return _("_Close");
#endif
    }
    
    virtual void extra_clicked() {}
    
  protected:
    WizardForm *_form;
    std::string _id;
    boost::signals2::signal<void (bool)> _signal_enter;
    boost::signals2::signal<void (bool)> _signal_leave;
    std::string _title;
    std::string _short_title;
    
    std::string execute_caption() const
    {
#ifdef __APPLE__
      return _("Execute");
#elif defined(_WIN32)
      return _("_Execute >");
#else
      return _("_Execute");
#endif
    }

    std::string finish_caption() const
    {
#ifdef __APPLE__
      return _("Finish");
#else
      return _("_Finish");
#endif
    }

    virtual std::string close_caption() const
    {
#ifdef __APPLE__
      return _("Close");
#else
      return _("_Close");
#endif
    }
    
  private:
    void filename_changed(mforms::TextEntry *entry);
    void browse_file_callback(mforms::TextEntry *entry, mforms::FileChooserType type,
                              const std::string &extensions);
  };

};


#endif
