/***************************** 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 *************************************/

#pragma once

#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_; }

private:
    int x_{0};
    int y_{0};
};


class IconObject : public virtual Counted
{
    friend class Folder;

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

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

    virtual const std::string& name() const;
    const std::string& className() const;
    const std::string& editorClassName() const;

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

    virtual std::string relativeName(IconObject*) const;
    virtual std::string makeFullName(const std::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 std::string&, bool create = true) const;
    virtual Folder* embeddedFolder(bool create = true) const;
    virtual bool isEmbedded();
    virtual bool isFolder() const { 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 std::string&);
    virtual Task* action(const Action&);
    virtual std::set<std::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 std::string&) const;
    virtual void setRequest(const Request&) = 0;

    virtual std::string dropText() const;

    virtual void drop(IconObject*);


    virtual const std::set<DependancyH>& dependancies();

    // Find

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

    // Move

    virtual void reparent(Folder*);
    virtual bool checkNewName(const std::string&);
    virtual bool rename(const std::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 initStateInfo();
    void updateStateInfo(bool broadcast = true);

    //
    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 std::vector<IconObjectH> subObjects(const std::string&, const Request&);
    virtual void setSubObjects(const std::string&, const std::vector<IconObjectH>&, Request&, bool clean = false);

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

    IconStatus status() const { return status_; }

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

    static std::vector<IconObject*> objects() { return objects_; }
    virtual bool storedAsRequestFile() const { return false; }

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

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

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

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

    static std::vector<IconObject*> objects_;

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

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

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