// $Id: newmenuitems.cpp,v 1.38 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.cpp
// functions to control the menuitem (a single line in a menu)
//
// Peter Beerli

#include <string>
#include "display.h"
#include "lamarc.h"         // EWFIX.P3 HACK HACK HACK -- for FinishRegistry()
                            // which we shouldn't even be contemplating using
#include "menudefs.h"
#include "newmenuitems.h"
#include "outputfile.h"
#include "registry.h"       // EWFIX.P3 HACK HACK HACK -- for FileDumpHandler
#include "ui_vars.h"        // EWFIX.P3 GIFTFROMLUCIAN Because of FinishRegistry()
#include "stringx.h"
#include "ui_interface.h"
#include "ui_strings.h"

SameLevelMenuItem::SameLevelMenuItem(std::string myKey, UIInterface & myUi, std::string myMenuKey)
    : KeyedMenuItem(myKey), ui(myUi) , menuKey(myMenuKey)
{
}

SameLevelMenuItem::~SameLevelMenuItem()
{
}

std::string SameLevelMenuItem::GetVariableText()
{
    return menustr::emptyString;
}

menu_return_type DoNothingHandler::InvokeMe(Display&)
{
    return menu_REDISPLAY;
}

FileDumpMenuItem::FileDumpMenuItem(UIInterface & myUi)
    : SameLevelMenuItem(">",myUi,"")
{
}

FileDumpMenuItem::~FileDumpMenuItem()
{
}

MenuInteraction_ptr FileDumpMenuItem::GetHandler(string)
{
    return MenuInteraction_ptr(new FileDumpHandler(ui));
}

std::string FileDumpMenuItem::GetText()
{
    return std::string("Generate Lamarc input file for these settings");
}

std::string
FileDumpHandler::beforeLoopOutputString()
{
    return "";
}

std::string
FileDumpHandler::inLoopOutputString()
{
    return "Enter a filename for a LAMARC input file.  Default is \""
        +  ui.doGetString(uistr::xmlOutFileName)
        +"\".\n";
}

std::string
FileDumpHandler::inLoopFailureOutputString()
{
    return "\nUnable to write to this file.\n";
}

std::string
FileDumpHandler::afterLoopSuccessOutputString()
{
    return string("");
}

std::string
FileDumpHandler::afterLoopFailureOutputString()
{
    return "Giving up after "+ToString(maxTries())
        + " unsuccessful attempts.\n";
}

bool
FileDumpHandler::handleInput(std::string input)
{
    std::string fileToWrite = ui.doGetString(uistr::xmlOutFileName);
    if (input.size() != 0)
    {
        fileToWrite = input;
    }
    std::ifstream testin(fileToWrite.c_str(), std::ios::in);
    std::ofstream testout(fileToWrite.c_str(), std::ios::out);
    if(testout)
    {
        if(testin)
        {
            string msg = "Warning:  overwrote an older version of \""
                + fileToWrite
                + "\".";
            ui.AddWarning(msg);
        }
        else
        {
            string msg = "Successfully wrote to \"" + fileToWrite + "\".";
            ui.AddWarning(msg);
        }
        FinishRegistry(ui);
        XMLOutfile xmlout(fileToWrite);
        xmlout.Display();
        // FinishRegistry moves any loci in the datapack to a new location.
        //  This is lethal if you want to do more with it, so we must revert
        //  it.  If we split the datapack in to phase 1/phase 2, this would go
        //  away.  --LS NOTE.
        ui.GetCurrentVars().datapackplus.RevertAllMovingLoci();
        return true;
    }
    else
    {
        return false;
    }
}

////

UndoMenuItem::UndoMenuItem(UIInterface & myUi)
    : SameLevelMenuItem("-",myUi,"")
{
}

UndoMenuItem::~UndoMenuItem()
{
}

std::string UndoMenuItem::GetText()
{
    return ui.GetUndoDescription();
}

bool UndoMenuItem::IsVisible()
{
    bool undoable = ui.CanUndo();
    return undoable;
}

MenuInteraction_ptr UndoMenuItem::GetHandler(string)
{
    return MenuInteraction_ptr(new UndoHandler(ui));
}

menu_return_type UndoHandler::InvokeMe(Display&)
{
    ui.Undo();
    return menu_REDISPLAY;
}

RedoMenuItem::RedoMenuItem(UIInterface & myUi)
    : SameLevelMenuItem("+",myUi,"")
{
}

RedoMenuItem::~RedoMenuItem()
{
}

std::string RedoMenuItem::GetText()
{
    return ui.GetRedoDescription();
}

bool RedoMenuItem::IsVisible()
{
    bool redoable =  ui.CanRedo();
    return redoable;
}

MenuInteraction_ptr RedoMenuItem::GetHandler(string)
{
    return MenuInteraction_ptr(new RedoHandler(ui));
}

menu_return_type RedoHandler::InvokeMe(Display&)
{
    ui.Redo();
    return menu_REDISPLAY;
}

BottomLineMenuItem::BottomLineMenuItem(UIInterface& ui)
    : m_ui(ui)
{
}

BottomLineMenuItem::~BottomLineMenuItem()
{
}

bool BottomLineMenuItem::Handles(string inputKey)
{
    if(CaselessStrCmp(inputKey, menustr::emptyString))
    { return true;};
    if(CaselessStrCmp(inputKey, key::dot))
    { return true;};
    if(CaselessStrCmp(inputKey, key::Q))
    { return true;};
    return false;
}

MenuInteraction_ptr BottomLineMenuItem::GetHandler(string inputKey)
{
    if(CaselessStrCmp(inputKey, menustr::emptyString))
    { return MenuInteraction_ptr(new GoUpHandler()); };
    if(CaselessStrCmp(inputKey, key::dot))
    { return MenuInteraction_ptr(new RunHandler(m_ui)); };
    if(CaselessStrCmp(inputKey, key::Q))
    { return MenuInteraction_ptr(new QuitHandler()); };
    return MenuInteraction_ptr(new DoNothingHandler());
}

BottomLineMenuItemAtTop::BottomLineMenuItemAtTop(UIInterface& ui)
    : BottomLineMenuItem(ui)
{
}

BottomLineMenuItemAtTop::~BottomLineMenuItemAtTop()
{
}

menu_return_type RunHandler::InvokeMe(Display & display)
{
    if (m_ui.IsReadyToRun())
    {
        return menu_RUN;
    }
    else
    {
        return DialogAcknowledge::InvokeMe(display);
    }
}

string RunHandler::outputString()
{
    return m_ui.WhatIsWrong();
}

SubMenuItem::SubMenuItem(std::string myKey,UIInterface & myui, NewMenuCreator * myCreator)
    : KeyedMenuItem(myKey), ui(myui), creator(myCreator)
{
}

SubMenuItem::~SubMenuItem()
{
    delete creator;
}

string SubMenuItem::GetText()
{
    // EWFIX.P5 REFACTOR there was a memory leak here, which was fixed
    // by having Create() return a shared pointer, but surely
    // we can do better
    return creator->Create()->Title();
}

string SubMenuItem::GetVariableText()
{
    return menustr::emptyString;
}

MenuInteraction_ptr SubMenuItem::GetHandler(std::string)
{
    // EWFIX.P5 REFACTOR there was a memory leak here, which was fixed
    // by having Create() return a shared pointer, but surely
    // we can do better
    NewMenu_ptr nm(creator->Create());
    NewMenu * np = nm.release();
    return MenuInteraction_ptr(np);
}

//____________________________________________________________________________________
