// $Id: gc_population_dialogs.cpp,v 1.23 2018/01/03 21:32:59 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: Mary Kuhner, Jon Yamato, and Joseph Felsenstein */


#include <cassert>

#include "gc_datastore.h"
#include "gc_errhandling.h"
#include "gc_event_ids.h"
#include "gc_dialog.h"
#include "gc_layout.h"
#include "gc_population.h"
#include "gc_population_dialogs.h"
#include "gc_strings.h"
#include "gc_structures_err.h"

#include "wx/checkbox.h"
#include "wx/log.h"
#include "wx/sizer.h"
#include "wx/statbox.h"
#include "wx/statline.h"
#include "wx/textctrl.h"

//------------------------------------------------------------------------------------

gcPopMergeChoice::gcPopMergeChoice(size_t popId)
    :
    m_popId(popId)
{
}

gcPopMergeChoice::~gcPopMergeChoice()
{
}

#if 0

wxString
gcPopMergeChoice::GetLabel(GCDataStore & dataStore)
{
    gcPopulation & popRef = dataStore.GetStructures().GetPop(m_popId);
    return popRef.GetName();
}

bool
gcPopMergeChoice::GetEnabled(GCDataStore & dataStore)
{
    return true;
}

bool
gcPopMergeChoice::GetSelected(GCDataStore & dataStore)
{
    return true;
}

void
gcPopMergeChoice::SetSelected(GCDataStore & dataStore, bool value)
{
}

#endif

void
gcPopMergeChoice::UpdateDisplayInitial(GCDataStore & dataStore)
{
    assert(m_box != NULL);

    // if it parsed, it's a legal choice
    m_box->Enable(true);

    // display settings next to check box
    const gcPopulation & popRef = dataStore.GetStructures().GetPop(m_popId);
    m_box->SetLabel(popRef.GetName());

    // we start with nothing checked
    m_box->SetValue(0);
}

void
gcPopMergeChoice::UpdateDisplayInterim(GCDataStore & dataStore)
// no changes needed since all pop merges are always legal
{
}

void
gcPopMergeChoice::UpdateDataInterim(GCDataStore & dataStore)
// all action happens at the enclosing set of choices
// and only at final update
{
}

void
gcPopMergeChoice::UpdateDataFinal(GCDataStore & dataStore)
// all action happens at the enclosing set of choices
{
}

wxWindow *
gcPopMergeChoice::MakeWindow(wxWindow * parent)
{
    m_box = new wxCheckBox(parent,-1,"");
    return m_box;
}

wxWindow *
gcPopMergeChoice::FetchWindow()
{
    return m_box;
}

size_t
gcPopMergeChoice::GetRelevantId()
{
    return m_popId;
}

//------------------------------------------------------------------------------------

gcPopMerge::gcPopMerge( wxWindow *                      parent,
                        size_t                          popId,
                        std::vector<gcChoiceObject*>    choices)
    :
    gcUpdatingChooseMulti(parent,gcstr::mergePopsInstructions,choices),
    m_popId(popId)
{
}

gcPopMerge::~gcPopMerge()
{
}

void
gcPopMerge::DoFinalForMulti(GCDataStore & dataStore, gcIdVec chosens)
{
    chosens.insert(chosens.begin(),m_popId);
    dataStore.GetStructures().MergePops(chosens);
}

wxString
gcPopMerge::NoChoicesText() const
{
    return gcstr::noChoicePopulation;
}

//------------------------------------------------------------------------------------

gcPopRename::gcPopRename(size_t popId)
    :
    m_popId(popId)
{
}

gcPopRename::~gcPopRename()
{
}

wxString
gcPopRename::FromDataStore(GCDataStore & dataStore)
{
    gcPopulation & popRef = dataStore.GetStructures().GetPop(m_popId);
    return popRef.GetName();
}

void
gcPopRename::ToDataStore(GCDataStore & dataStore, wxString newText)
{
    newText.Replace(" ","_");
    gcPopulation & popRef = dataStore.GetStructures().GetPop(m_popId);
    dataStore.GetStructures().Rename(popRef,newText);
}

//------------------------------------------------------------------------------------

gcPopEditDialog::gcPopEditDialog(   wxWindow *      parent,
                                    GCDataStore &   dataStore,
                                    size_t          popId,
                                    bool            forJustCreatedObj)
    :
    gcUpdatingDialog(   parent,
                        dataStore,
                        forJustCreatedObj
                        ?
                        gcstr::addPop
                        :
                        wxString::Format(gcstr::editPop,
                                         dataStore.GetStructures().GetPop(popId).GetName().c_str()),
                        forJustCreatedObj),
    m_popId(popId)
{
}

gcPopEditDialog::~gcPopEditDialog()
{
}

void
gcPopEditDialog::DoDelete()
{
    gcPopulation & popRef = m_dataStore.GetStructures().GetPop(m_popId);
    m_dataStore.GetStructures().RemovePop(popRef);
}

//------------------------------------------------------------------------------------

bool
DoDialogEditPop(wxWindow *      parentWindow,
                GCDataStore &   dataStore,
                size_t          popId,
                bool            forJustCreatedObj)
{
    gcPopEditDialog dialog(parentWindow,dataStore,popId,forJustCreatedObj);

    // build the dialog
    gcDialogCreator creator;
    wxBoxSizer * contentSizer = new wxBoxSizer(wxHORIZONTAL);

    // editing the name always ok
    gcTextHelper * popRenameHelp = new gcPopRename(popId);
    gcUpdatingComponent * rename = new gcUpdatingTextCtrl(&dialog,
                                                          forJustCreatedObj ? gcstr::populationNewName : gcstr::populationRename,
                                                          popRenameHelp);
    contentSizer->Add(rename,
                      1,
                      wxALL | wxALIGN_CENTER | wxEXPAND,
                      gclayout::borderSizeSmall);
    creator.AddComponent(dialog,rename);

    // merging pops only for existing pops
    if(!forJustCreatedObj)
    {
        std::vector<gcChoiceObject*> popChoices;
        gcDisplayOrder ids = dataStore.GetStructures().GetDisplayablePopIds();
        for(gcDisplayOrder::iterator iter=ids.begin(); iter != ids.end(); iter++)
        {
            size_t id = *iter;
            if(id != popId)
            {
                gcPopMergeChoice * choice = new gcPopMergeChoice(id);
                popChoices.push_back(choice);
            }
        }

        gcUpdatingComponent * right = new gcPopMerge( &dialog, popId,popChoices);
        contentSizer->Add(new wxStaticLine(&dialog,-1,wxDefaultPosition,wxDefaultSize,wxLI_VERTICAL),
                          0,
                          wxALL | wxALIGN_CENTER | wxEXPAND,
                          gclayout::borderSizeSmall);
        contentSizer->Add(right,
                          1,
                          wxALL | wxALIGN_CENTER | wxEXPAND,
                          gclayout::borderSizeSmall);
        creator.AddComponent(dialog,right);
    }

    creator.PlaceContent(dialog,contentSizer);

    // invoke the dialog
    return dialog.Go();
}

//------------------------------------------------------------------------------------

bool
gcActor_PopAdd::OperateOn(wxWindow * parent, GCDataStore & dataStore)
{
    gcPopulation & popRef = dataStore.GetStructures().MakePop("",true);
    return DoDialogEditPop(parent,dataStore,popRef.GetId(),true);
}

//------------------------------------------------------------------------------------

bool
gcActor_Pop_Edit::OperateOn(wxWindow * parent, GCDataStore & dataStore)
{
    return DoDialogEditPop(parent,dataStore,m_popId,false);
}

//____________________________________________________________________________________
