// $Id: setmenuitem.h,v 1.32 2018/01/03 21:33:01 mkkuhner Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


// Menuitem.h
// is line in the menu and consists of a (key, text, handlerobject)
//
// Peter Beerli

#ifndef SETMENUITEM_H
#define SETMENUITEM_H

#include <string>
#include "dialogrepeat.h"
#include "errhandling.h"
#include "menuitem.h"
#include "menuinteraction.h"
#include "stringx.h"
#include "ui_interface.h"
#include "ui_constants.h"
#include "vectorx.h"
#include "menutypedefs.h"

class SetDialog : public DialogRepeat
{
  private:
    SetDialog(); //undefined
  protected:
    UIInterface & ui;
    std::string menuKey;
    const UIId id;
    //
    bool haveError;
    std::string currError;
    //
    std::string getText()
    { return ui.doGetDescription(menuKey,id);};
    virtual void stuffValIntoUI(std::string val)
    { ui.doSet(menuKey,val,id);};
  public:
    SetDialog(UIInterface & myui, std::string myMenuKey, UIId myId)
        : ui(myui) , menuKey(myMenuKey), id(myId) {};
    virtual ~SetDialog() {};
    virtual long maxTries()
    { return 3;};
    virtual std::string beforeLoopOutputString()
    { return "";};
    virtual std::string inLoopOutputString();
    virtual std::string inLoopFailureOutputString()
    {
        if (haveError)
        {
            return currError;
        }
        else
        {
            implementation_error e("Unknown menu error");
            throw e;
        }
    };
    virtual std::string afterLoopSuccessOutputString()
    { return "";};
    virtual std::string afterLoopFailureOutputString()
    { return string("Unable to accept your input\n")+
            "Leaving \""+getText()+"\" unchanged\n";};
    virtual bool handleInput(std::string input)
    {   haveError = false;
        try
        {
            stuffValIntoUI(input);
        }
        catch (data_error& e)
        {
            currError = e.what();
            haveError = true;
            return false;
        }
        return true;
    };
    virtual void doFailure()
    {};

  private:
    std::string getMin() { return ui.doGetMin(menuKey,id);};
    std::string getMax() { return ui.doGetMax(menuKey,id);};
};

class SetMenuItem : public KeyedMenuItem
{
  private:
    SetMenuItem(); //undefined
  protected:
    UIInterface & ui;
    std::string menuKey;
    virtual UIId GetId() = 0;
  public:
    SetMenuItem(std::string myKey, UIInterface & myui, std::string mk );
    SetMenuItem(std::string myKey, UIInterface & myui, std::string mk, UIId myId);
    virtual ~SetMenuItem();
    // ---- MenuItem methods
    virtual std::string GetText();
    virtual std::string GetVariableText();
    virtual MenuInteraction_ptr GetHandler(std::string input);
    virtual bool IsVisible();
    virtual bool IsConsistent();
};

class SetMenuItemNoId : public SetMenuItem
{
  private:
    SetMenuItemNoId(); //undefined
  protected:
    virtual UIId GetId();
  public:
    SetMenuItemNoId(std::string myKey, UIInterface & myui, std::string myMenuKey);
    virtual ~SetMenuItemNoId();
};

class SetMenuItemId : public SetMenuItem
{
  private:
    SetMenuItemId(); //undefined
  protected:
    UIId id;
    virtual UIId GetId();
  public:
    SetMenuItemId(std::string myKey, UIInterface & myui, std::string myMenuKey, UIId myId);
    virtual ~SetMenuItemId();
};

class NewToggleHandler : public MenuInteraction
{
  private:
    NewToggleHandler(); //undefined
  protected:
    UIInterface & ui;
    std::string menuKey;
    UIId id;
  public:
    NewToggleHandler(UIInterface & myui, std::string myMenuKey, UIId myId)
        : ui(myui),menuKey(myMenuKey),id(myId) {};
    ~NewToggleHandler() {};
    virtual menu_return_type InvokeMe(Display &)
    { ui.doToggle(menuKey,id); return menu_REDISPLAY;};
};

class ToggleMenuItemNoId : public SetMenuItemNoId
{
  private:
    ToggleMenuItemNoId(); //undefined
  public:
    ToggleMenuItemNoId(std::string myKey, UIInterface & myui, std::string myMenuKey )
        : SetMenuItemNoId(myKey,myui,myMenuKey) {};
    ~ToggleMenuItemNoId() {};
    virtual MenuInteraction_ptr GetHandler(std::string)
    { return MenuInteraction_ptr(new NewToggleHandler(ui,menuKey,GetId()));};
};

class ToggleMenuItemId : public SetMenuItemId
{
  public:
    ToggleMenuItemId(std::string myKey, UIInterface & myui, std::string myMenuKey, UIId myId)
        : SetMenuItemId(myKey,myui,myMenuKey,myId) {};
    ~ToggleMenuItemId() {};
    virtual MenuInteraction_ptr GetHandler(std::string)
    { return MenuInteraction_ptr(new NewToggleHandler(ui,menuKey,GetId()));};
};

class MenuDisplayGroupBaseImplementation : public MenuDisplayGroup
{
  private:
    MenuDisplayGroupBaseImplementation(); //undefined
  protected:
    UIInterface & ui;
    std::string menuKey;
    virtual MenuInteraction_ptr MakeOneHandler(UIId id) = 0;
  public:
    MenuDisplayGroupBaseImplementation(UIInterface & myui, std::string myMenuKey);
    virtual ~MenuDisplayGroupBaseImplementation();
    virtual std::string GetKey(UIId id);
    virtual std::string GetText(UIId id);
    virtual std::string GetVariableText(UIId id);
    virtual bool Handles(std::string input);
    virtual MenuInteraction_ptr GetHandler(std::string input);
};

class SetMenuItemGroup : public MenuDisplayGroupBaseImplementation
{
  private:
    SetMenuItemGroup(); //undefined
  protected:
    virtual MenuInteraction_ptr MakeOneHandler(UIId id);
  public:
    SetMenuItemGroup(UIInterface & myui, std::string myMenuKey);
    virtual ~SetMenuItemGroup();
};

class ToggleMenuItemGroup : public MenuDisplayGroupBaseImplementation
{
  private:
    ToggleMenuItemGroup(); //undefined
  protected:
    virtual MenuInteraction_ptr MakeOneHandler(UIId id);
  public:
    ToggleMenuItemGroup(UIInterface & myui, std::string myMenuKey);
    virtual ~ToggleMenuItemGroup();
};

#endif  // SETMENUITEM_H

//____________________________________________________________________________________
