/*
 * Copyright (C) 2002,2003,2004 Daniel Heck
 * Copyright (C) 2007,2008 Ronald Lamprecht
 *
 * 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; either version 2
 * of the License, or (at your option) any later version.
 *
 * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "items.hh"

#include "errors.hh"
#include "main.hh"
#include "display.hh"
#include "player.hh"
#include "client.hh"
#include "SoundEffectManager.hh"
#include "server.hh"
#include "world.hh"
#include "Inventory.hh"
#include "ItemHolder.hh"

#include "ecl_util.hh"

using namespace std;

namespace enigma {

/* -------------------- Item implementation -------------------- */

Item::Item() {
}

void Item::kill() {
    KillItem(get_pos());
}

void Item::replace(std::string kind) {
    Item *newitem = MakeItem(kind.c_str());
    transferName(newitem);     // TODO check where transfer of identity is better
    setup_successor(newitem);  // hook for subclasses
    SetItem(get_pos(), newitem);
}

void Item::transform(std::string kind) {
    Item *newitem = MakeItem(kind.c_str());
    transferIdentity(newitem);  // subclasses may hook this call
    SetItem(get_pos(), newitem);
}

std::string Item::getClass() const {
    return get_traits().name;
}

Value Item::getAttr(const std::string &key) const {
    if (key == "liftable") {
        return !isStatic();
    } else if (key == "portable") {
        return isPortable();
    } else if (key == "freezable") {
        return isFreezable();
    }
    return GridObject::getAttr(key);
}

std::string Item::get_inventory_model() {
    return getKind();
}

void Item::init_model() {
    const ItemTraits &tr = get_traits();
    if (tr.flags & itf_invisible)
        set_model("invisible");
    else if (tr.flags & itf_animation)
        set_anim(tr.name);
    else
        set_model(tr.name);
}

void Item::stone_change(Stone * /*st*/) {
}

void Item::on_stonehit(Stone * /*st*/) {
}

void Item::processLight(Direction d) {
    if (get_traits().flags & itf_inflammable) {
        replace("it_explosion_nil");
    } else
        GridObject::processLight(d);
}

double Item::getFriction(ecl::V2 position, double defaultFriction, Actor *a) {
    return defaultFriction;
}

ecl::V2 Item::calcMouseforce(Actor *a, ecl::V2 mouseForce, ecl::V2 floorForce) {
    return floorForce;
}

void Item::on_drop(Actor * /*a*/) {
}

void Item::drop(Actor *a, GridPos p) {
    SetItem(p, this);
    on_drop(a);
}

void Item::on_pickup(Actor * /*a*/) {
}

bool Item::can_drop_at(GridPos p) {
    return GetItem(p) == nullptr;
}

ItemAction Item::activate(Actor * /*a*/, GridPos /*p*/) {
    return ITEM_DROP;
}

bool Item::isStatic() const {
    return get_traits().flags & itf_static;
}

bool Item::isPortable() const {
    return !isStatic() || (get_traits().flags & itf_portable);
}

bool Item::isFreezable() const {
    return isPortable() || (get_traits().flags & itf_freezable);
}

void Item::add_force(Actor *, ecl::V2 &) {
}

bool Item::actor_hit(Actor *actor) {
    const ItemTraits &tr = get_traits();
    if (isStatic())
        return false;
    else {
        double radius = 0.3;
        if (tr.radius != 0.0)
            radius = tr.radius;
        return length(actor->get_pos() - get_pos().center()) < radius;
    }
}

std::list<GridPos> Item::warpSpreadPos(bool isWater) {
    std::list<GridPos> results;
    return results;
}

}  // namespace enigma
