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

#include <grtpp.h>
#include <algorithm>
#include "tree_model.h"

#include "wbpublic_public_interface.h"

namespace bec {

  class WBPUBLICBACKEND_PUBLIC_FUNC StructsTreeBE : public TreeModel
  {
  public:
    enum DisplayMode {
      ByName,
        ByHierarchy,
        ByPackage
    };
    enum StructTreeColumns {
        Name,
        Caption,
        Type
    };

    StructsTreeBE(grt::GRT *grt);

    virtual int count_children(const NodeId &parent);
    virtual NodeId get_child(const NodeId &parent, int index);

    virtual bool get_field(const NodeId &node, int column, std::string &value);
    virtual std::string get_field_description(const NodeId &node, int column);
    virtual IconId get_field_icon(const NodeId &node, int column, IconSize size);
    virtual grt::Type get_field_type(const NodeId &node, int column);

    // not for windows
    bool get_row(const NodeId &node,
                 IconId &caption_icon,
                 std::string &name,
                 std::string &caption,
                 std::string &type);

    virtual void refresh();

    void set_display_mode(DisplayMode mode);

  private:
    enum TreeNodeType {
      NPackage,
        NStruct,
        NFunction,
        NMember,
        NSignal
    };

    friend class NodeCompare;

    struct Node;

    struct DeleteNode 
    { 
      void operator () (Node* n) const { delete n; } 
    };

    struct Node {
      typedef std::vector<Node *> NodeVector;

      NodeVector children;
      TreeNodeType type;
      std::string name;
      grt::MetaClass *gstruct;

      Node()
      {}

      Node(const Node& n)
        : children(n.children), type(n.type), name(n.name), gstruct(n.gstruct)
      {}

      Node(TreeNodeType t, const std::string &n)
        : type(t), name(n)
      {}

      Node(TreeNodeType t, const std::string &n, grt::MetaClass *gs)
        : type(t), name(n), gstruct(gs)
      {}

      ~Node()
      {
        std::for_each(children.begin(), children.end(), DeleteNode());
      }

      Node& operator = (const Node& n)
      {
        children.assign(n.children.begin(), n.children.end());
        type= n.type;
        name= n.name;
        gstruct= n.gstruct;
        return *this;
      }
    };
    
    class NodeCompare
      //: public std::binary_function<Node, Node, bool>
    {
    protected:
      friend class StructsTreeBE;
      
      StructsTreeBE *_owner;
      NodeCompare(StructsTreeBE *owner) : _owner(owner) {}
    public:
      bool operator() (const Node *ln, const Node *rn) const
      {
        if (ln->type != rn->type)
          return ln->type < rn->type;
        return ln->name < rn->name;
      }
    };
    
    grt::GRT *_grt;
    DisplayMode _mode;

    Node _root;

    //bool get_node_for_id(const NodeId &id, Node &node);
    Node *get_node_for_id(const NodeId &id);
    
    void refresh_by_name();
    void refresh_by_hierarchy(const grt::MetaClass *parent, Node *parnode);
    void refresh_by_package();
  };  
};

#endif /* _GRT_STRUCTS_LIST_H_ */
