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

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

#include "IconFactory.h"

#include "IconClass.h"
#include "IconInfo.h"
//#include "Unknown.h"
#include "Folder.h"

#include "FolderInfo.h"
#include "Request.h"
#include "TemporaryObject.h"

#include <assert.h>

static map<string, IconFactory*>* makers = 0;

IconFactory::IconFactory(const string& name)
{
    if (makers == 0)
        makers = new map<string, IconFactory*>;

    (*makers)[name] = this;
}

IconFactory::~IconFactory()
{
    // Not called
}

//For folders name should contain the full path!!!
IconObject* IconFactory::create(Folder* parent, const string& name, const IconClass& kind, IconInfo* info)
{
    IconObject* o = 0;

    // Try class, then type
    map<string, IconFactory*>::iterator j = makers->find(kind.name());
    if (j == makers->end())
        j = makers->find(kind.type());
    if (j == makers->end()) {
        marslog(LOG_WARN, "Unknown icon type=%s [file=%s]", kind.type().c_str(), name.c_str());
        // o = new Unknown(parent,kind,name,info);
        o = 0;
    }
    else
        o = (*j).second->make(parent, kind, name, info);

    if (o != 0) {
        parent->adopt(o);
        o->createFiles();
    }

    return o;
}

IconObject* IconFactory::createTemporary(IconObject* o, const Request& r, const IconClass* c)
{
    return new TemporaryObject(o, r, c);
}

IconObject* IconFactory::create(Folder* parent, const string& name, const IconClass& kind)
{
    return create(parent, name, kind, 0);
}

IconObject* IconFactory::create(Folder* parent, const string& name, const IconClass& kind, int x, int y)
{
    IconInfo* info = new IconInfo(kind.name(), x, y);
    return create(parent, name, kind, info);
}

IconObject* IconFactory::create(Folder* parent, const string& name)
{
    return create(parent, name, IconInfo::undefX(), IconInfo::undefY());
}

IconObject* IconFactory::create(Folder* parent, const string& name, int x, int y)
{
    FolderInfo* folderInfo = 0;
    IconInfo* info         = 0;
    string dirName, fileName;

    Path path  = parent->path();
    dirName    = path.str();
    fileName   = path.add(name).str();
    folderInfo = parent->folderInfo();
    info       = folderInfo->find(name);

    if (info) {
        const IconClass& ic = IconClass::find(info->type());
        return create(parent, name, ic, info);
    }

    //If there is no folderinfo available we see if there is a
    //dotfile to get the type and the positions
    else {
        Path actPath(dirName);
        Path dot = actPath.add(string(".") + name);
        Request dotInfo(dot);

        //If there is no dotfile we guess the file type
        if (!dotInfo) {
            dotInfo               = Request("USER_INTERFACE");
            const IconClass& ic   = IconClass::guess(fileName);
            dotInfo("ICON_CLASS") = ic.name().c_str();

            info = new IconInfo(dotInfo);
            if (x != IconInfo::undefX() && y != IconInfo::undefY())
                info->position(x, y);

            return create(parent, name, ic, info);
        }
        else {
            const char* type    = dotInfo("ICON_CLASS");
            const IconClass& ic = IconClass::find(type);

            info = new IconInfo(dotInfo);
            if (x != IconInfo::undefX() && y != IconInfo::undefY())
                info->position(x, y);

            return create(parent, name, ic, info);
        }
    }
}


IconObject* IconFactory::create(const string& name, const IconClass& kind)
{
    IconObject* o = IconObject::search(name);
    if (o)
        return o;

    //cout << "IconFactory::create " << name << endl;
    string dir  = mdirname(name.c_str());
    string base = mbasename(name.c_str());

    Folder* f = dynamic_cast<Folder*>(create(dir, IconClass::find("FOLDER")));
    return f ? create(f, base, kind) : 0;
}

IconObject* IconFactory::create(IconObject* /*o*/, const Request& /*r*/,
                                const IconClass* /*c*/)
{
    assert(0);
    return 0;
    //return new Temporary(o,r,c);
}

IconObject* IconFactory::create(Folder* parent, const Request& r, int x, int y)
{
    const char* kind = r.getVerb();
    const char* name = r("_NAME");

    string kind1(kind);  //it is needed on alpha
    const IconClass& c = IconClass::find(kind1);

    // The command below was causing memory problems on alpha.
    // Therefore, it was re-coded in a different way
    //	string n = name?mbasename(name):c.defaultName();
    string n;
    if (name)
        n = mbasename(name);
    else
        n = c.defaultName();

    n = parent->uniqueName(n);

    IconObject* o = create(parent, n, c, x, y);

    r.save(o->path());
    return o;
}
