#include <Wt/WApplication>
#include <Wt/WEnvironment>

#include <Wt/WTreeView>
#include <Wt/WStandardItem>
#include <Wt/WStandardItemModel>
#include <Wt/WItemDelegate>

#include <Wt/WText>
#include <Wt/WContainerWidget>
#include <Wt/WLineEdit>

#include <string>
#include <iostream>
#include <limits>
#include <boost/bind.hpp>
#include <boost/any.hpp>

using namespace std;
using namespace Wt;


class MyDelegate: public Wt::WItemDelegate
{
public:
    MyDelegate(Wt::WObject *parent = 0) : WItemDelegate(parent) {};
    virtual ~MyDelegate(){};
private:
    Wt::WWidget* createEditor(const Wt::WModelIndex& index, Wt::WFlags<Wt::ViewItemRenderFlag> flags) const;
    void Close(Wt::WWidget *editor, bool save) const;
    boost::any editState(Wt::WWidget *editor) const;
};




class cntWidget: public Wt::WText {
public:
    cntWidget(Wt::WContainerWidget *parent = 0): Wt::WText(parent) {++cnt_; std::cout << "CNT widget = "<< cnt_<<std::endl;};
    ~cntWidget(){--cnt_; std::cout << " CNT widget = "<< cnt_<< std::endl;};
    static int cnt_;
};
int cntWidget::cnt_=0;


Wt::WWidget* MyDelegate::createEditor(const Wt::WModelIndex& index, Wt::WFlags<Wt::ViewItemRenderFlag> flags) const{
    // reimplement the default editor to add a validator
    Wt::WContainerWidget *editor  = new Wt::WContainerWidget();
    Wt::WLineEdit *line = new Wt::WLineEdit();
    line->escapePressed().connect(boost::bind(&MyDelegate::Close, this, editor, false));
    line->blurred().connect(boost::bind(&MyDelegate::Close, this, editor, true));
    if (flags & RenderFocused) line->setFocus();
    editor ->addWidget(line);
    editor ->addWidget(new cntWidget());
    return editor ;
}

void MyDelegate::Close(Wt::WWidget *editor, bool save) const {
    closeEditor().emit(editor, save);
    cout << "closeEditor emitted" << endl;
}

boost::any MyDelegate::editState(Wt::WWidget *editor) const {
    Wt::WContainerWidget *w = dynamic_cast<Wt::WContainerWidget *>(editor);
    Wt::WLineEdit *lineEdit = dynamic_cast<Wt::WLineEdit *>(w->widget(0));
    return boost::any(lineEdit->text().narrow());
}

Wt::WApplication* createApp(const Wt::WEnvironment& env) {
    WApplication* app = new WApplication(env);
    app->setCssTheme("polished");

    Wt::WTreeView* tree = new WTreeView(app->root());
    WStandardItemModel* model = new WStandardItemModel(app->root());

    WStandardItem *item = new WStandardItem("na");
    item->setFlags(ItemIsEditable);
    model->setItem(0,1,item);
    item = new WStandardItem("name");
    item->setFlags(ItemIsEditable);
    model->setItem(0,0,item);
    item = new WStandardItem("num");
    item->setFlags(ItemIsEditable);
    model->setItem(1,0,item);
    item = new WStandardItem("3");
    item->setFlags(ItemIsEditable);
    model->setItem(1,1,item);

    tree->setModel(model);
    tree->setItemDelegateForColumn(0, new MyDelegate(app->root()));

    tree->setItemDelegateForColumn(1, new MyDelegate(app->root()));
    tree->setAlternatingRowColors(true);
    tree->setSelectionMode(SingleSelection);
    tree->setEditTriggers(WAbstractItemView::SingleClicked);
    tree->setHeight(200);
    return app;
}


int main(int argc, char** argv) {
    cout << WT_CLASS << endl;
    return WRun(argc,argv,&createApp);
}

