/***************************** LICENSE START ***********************************

 Copyright 2013 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#ifndef IconObject_H
#define IconObject_H

#include "Counted.h"

class IconClass;
class IconInfo;
//class FolderObserver;
class Action;
class Queue;
class Folder;
//class CommandObserver;
class Editor;
class Action;
class Request;
class Task;
class Log;
class MvQLogDialog;
class MvIconLanguage;
class MvIconParameter;

#include "Metview.h"
#include "Path.h"
#include "Dependancy.h"
#include "IconObserver.h"

class IconObject;
class IconObjectH;


class IconPosition
{
public:
    IconPosition(int x = 0, int y = 0) :
        x_(x),
        y_(y) {}
    void setPosition(int x, int y)
    {
        x_ = x;
        y_ = y;
    }
    int x() const { return x_; }
    int y() const { return y_; }

protected:
    int x_;
    int y_;
};


class IconObject : public virtual Counted
{
    friend class Folder;

public:
    enum IconStatus
    {
        DefaultStatus,
        ReadyStatus,
        WaitingStatus,
        ErrorStatus
    };

    IconObject(Folder*, const IconClass&, const string&, IconInfo*);
    virtual ~IconObject();

    virtual const string& name() const;
    virtual const string& className() const;

    virtual string dotName(const string&) const;
    virtual string embeddedName(const string&) const;
    virtual string fullName() const;

    virtual string relativeName(IconObject*) const;
    virtual string makeFullName(const string&) const;

    virtual Path path() const;
    // This Path method will only be all by the Shell Task.
    // For all object it will call the path method.
    // For Temporary Objects, it will return the PATH of the attached request.
    // This is done to enable the visualisation of the MAGML Objects
    // without possible side effects!
    virtual Path pathForShellTask() const { return path(); }
    virtual Path dotPath() const;
    virtual Path embeddedPath() const;

    virtual const IconClass& iconClass() const;
    virtual const IconClass& editorClass() const;

    virtual Folder* parent() const;
    virtual Folder* embeddedFolder(const string&, bool create = true) const;
    virtual Folder* embeddedFolder(bool create = true) const;
    virtual bool isEmbedded();
    virtual bool isFolder() { return false; }

    // Info

    virtual IconInfo& info() const;
    virtual void saveInfo();

    IconPosition& tmpPos() { return tmpPos_; }

    virtual bool visible() const;

    // Actions

    virtual void doubleClick();
    virtual void command(const string&);
    virtual Task* action(const Action&);
    virtual set<string> can();

    virtual void toWastebasket();
    virtual void duplicate();
    virtual void removeFiles();
    virtual void edit();
    virtual void edit2();
    virtual void showLog();

    virtual void destroy();
    virtual void empty();

    virtual IconObject* clone(Folder*, int x, int y, bool update = false);
    virtual IconObject* clone(Folder*, bool update = false);

    virtual void editor(Editor*);
    virtual Editor* editor();
    void raiseEditor();

    virtual void logWindow(MvQLogDialog*);
    virtual MvQLogDialog* logWindow();

    virtual Request request() const = 0;
    virtual Request fullRequest() const;
    virtual MvIconLanguage& language() const;
    virtual Request requestForVerb(const string&) const;
    virtual void request(const Request&) = 0;

    virtual string dropText() const;

    virtual void drop(IconObject*);


    virtual const set<DependancyH>& dependancies();

    // Find

    virtual IconObject* find(const vector<string>&);
    virtual IconObject* find(const string&);


    // Move

    virtual void reparent(Folder*);
    virtual bool checkNewName(const string&);
    virtual bool rename(const string&);
    virtual bool renamable() const;
    virtual bool temporary() const;

    void position(int, int);
    virtual bool locked() const;
    virtual bool isLink() const;
    virtual bool isBrokenLink() const;
    virtual bool isInTimer() const;
    virtual void lock();

    //

    void addObserver(IconObserver*);
    void removeObserver(IconObserver*);

    //

    virtual void notifyWaiting();
    virtual void notifyError();
    virtual void notifyChanged();
    virtual void notifyReady();
    virtual void notifyOpened();
    virtual void notifyClosed();
    virtual void notifyDestroyed();


    virtual bool sameAs(IconObject*);
    virtual void touch();
    //


    virtual void createFiles();

    // Status

    virtual void created();
    virtual void modified();

    virtual Log& log();
    virtual Path logPath();

    // ---
    virtual vector<IconObjectH> subObjects(const string&, const Request&);
    virtual void setSubObjects(const string&, const vector<IconObjectH>&, Request&, bool clean = false);

    static IconObject* search(const string& fullName);
    static IconObject* search(IconObject&, const string& relativeName);

    IconStatus status() const { return status_; }

    bool match(const std::string&, const std::string&);
    virtual bool checkRequest();

    static vector<IconObject*> objects() { return objects_; }

protected:
    //Use and implement it with extra care!!!
    virtual bool recheckIconClass() { return false; }

    virtual void print(ostream&) const;
    virtual void reset();

    string name_;
    Folder* parent_;
    IconClass* class_;
    IconInfo* info_;
    Queue* queue_;
    Log* log_;
    Editor* editor_;
    MvQLogDialog* logWindow_;
    bool locked_;
    bool link_;
    IconPosition tmpPos_;

    set<DependancyH> dependancies_;
    set<IconObserver*> observers_;
    IconStatus status_;

    static vector<IconObject*> objects_;

private:
    // No copy allowed
    IconObject(const IconObject&);
    IconObject& operator=(const IconObject&);

    friend ostream& operator<<(ostream& s, const IconObject& p)
    {
        p.print(s);
        return s;
    }
};

class IconObjectH : public Handle<IconObject>
{
public:
    IconObjectH(IconObject* o = 0) :
        Handle<IconObject>(o) {}
};

#endif
