// location.cpp
//
// Copyright (C) 2003, Chris Laurel <claurel@shatters.net>
//
// 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.

#include "location.h"

#include <cstddef>
#include <cstring>

#include <Eigen/Geometry>

#include <celengine/body.h>
#include <celutil/gettext.h>

// size_t and strncmp are used by the gperf output code
using std::size_t;
using std::strncmp;

namespace
{

// lookup table generated by gperf (location.gperf)
#include "location.inc"

} // end unnamed namespace

const std::string&
Location::getName(bool i18n) const
{
    return i18n && !i18nName.empty() ? i18nName : name;
}

void
Location::setName(const std::string& _name)
{
    name = _name;
    i18nName = D_(_name.c_str());
    if (name == i18nName)
        i18nName = {};
}

std::string
Location::getPath(const StarDatabase* starDB, char delimiter) const
{
    if (parent)
        return parent->getPath(starDB, delimiter) + delimiter + name;
    else
        return name;
}

Eigen::Vector3f
Location::getPosition() const
{
    return position;
}

void
Location::setPosition(const Eigen::Vector3f& _position)
{
    position = _position;
}

float
Location::getSize() const
{
    return size;
}

void
Location::setSize(float _size)
{
    size = _size;
}

float
Location::getImportance() const
{
    return importance;
}

void
Location::setImportance(float _importance)
{
    importance = _importance;
}

const std::string&
Location::getInfoURL() const
{
    return infoURL;
}

Location::FeatureType
Location::getFeatureType() const
{
    return featureType;
}

void
Location::setFeatureType(Location::FeatureType _featureType) // cppcheck-suppress passedByValue
{
    featureType = _featureType;
}

Location::FeatureType
Location::parseFeatureType(std::string_view s)
{
    auto ptr = FeatureNamesMap::getFeatureType(s.data(), s.size());
    return ptr == nullptr
        ? FeatureType::Other
        : ptr->featureType;
}

Body*
Location::getParentBody() const
{
    return parent;
}

void
Location::setParentBody(Body* _parent)
{
    parent = _parent;
}

/*! Get the position of the location relative to its body in
 *  the J2000 ecliptic coordinate system.
 */
Eigen::Vector3d
Location::getPlanetocentricPosition(double t) const
{
    if (parent == nullptr)
        return position.cast<double>();

    Eigen::Quaterniond q = parent->getEclipticToBodyFixed(t);
    return q.conjugate() * position.cast<double>();
}

Eigen::Vector3d
Location::getHeliocentricPosition(double t) const
{
    if (parent == nullptr)
        return position.cast<double>();

    return parent->getAstrocentricPosition(t) + getPlanetocentricPosition(t);
}
