/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------

Copyright (c) 2006-2017, assimp team

All rights reserved.

Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.

* Redistributions in binary form must reproduce the above
  copyright notice, this list of conditions and the
  following disclaimer in the documentation and/or other
  materials provided with the distribution.

* Neither the name of the assimp team, nor the names of its
  contributors may be used to endorse or promote products
  derived from this software without specific prior
  written permission of the assimp team.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

----------------------------------------------------------------------
*/

/** @file  IFCProfile.cpp
 *  @brief Read profile and curves entities from IFC files
 */

#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"

namespace Assimp {
namespace IFC {
namespace {


// --------------------------------------------------------------------------------
// Conic is the base class for Circle and Ellipse
// --------------------------------------------------------------------------------
class Conic : public Curve {
public:
    // --------------------------------------------------
    Conic(const IfcConic& entity, ConversionData& conv)
    : Curve(entity,conv) {
        IfcMatrix4 trafo;
        ConvertAxisPlacement(trafo,*entity.Position,conv);

        // for convenience, extract the matrix rows
        location = IfcVector3(trafo.a4,trafo.b4,trafo.c4);
        p[0] = IfcVector3(trafo.a1,trafo.b1,trafo.c1);
        p[1] = IfcVector3(trafo.a2,trafo.b2,trafo.c2);
        p[2] = IfcVector3(trafo.a3,trafo.b3,trafo.c3);
    }

    // --------------------------------------------------
    bool IsClosed() const {
        return true;
    }

    // --------------------------------------------------
    size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
        ai_assert( InRange( a ) );
        ai_assert( InRange( b ) );

        a *= conv.angle_scale;
        b *= conv.angle_scale;

        a = std::fmod(a,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
        b = std::fmod(b,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
        const IfcFloat setting = static_cast<IfcFloat>( AI_MATH_PI * conv.settings.conicSamplingAngle / 180.0 );
        return static_cast<size_t>( std::ceil(std::abs( b-a)) / setting);
    }

    // --------------------------------------------------
    ParamRange GetParametricRange() const {
        return std::make_pair(static_cast<IfcFloat>( 0. ), static_cast<IfcFloat>( AI_MATH_TWO_PI / conv.angle_scale ));
    }

protected:
    IfcVector3 location, p[3];
};

// --------------------------------------------------------------------------------
// Circle
// --------------------------------------------------------------------------------
class Circle : public Conic {
public:
    // --------------------------------------------------
    Circle(const IfcCircle& entity, ConversionData& conv)
        : Conic(entity,conv)
        , entity(entity)
    {
    }

    // --------------------------------------------------
    IfcVector3 Eval(IfcFloat u) const {
        u = -conv.angle_scale * u;
        return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(std::cos(u))*p[0] +
            static_cast<IfcFloat>(std::sin(u))*p[1]);
    }

private:
    const IfcCircle& entity;
};


// --------------------------------------------------------------------------------
// Ellipse
// --------------------------------------------------------------------------------
class Ellipse : public Conic {
public:
    // --------------------------------------------------
    Ellipse(const IfcEllipse& entity, ConversionData& conv)
    : Conic(entity,conv)
    , entity(entity) {
        // empty
    }

    // --------------------------------------------------
    IfcVector3 Eval(IfcFloat u) const {
        u = -conv.angle_scale * u;
        return location + static_cast<IfcFloat>(entity.SemiAxis1)*static_cast<IfcFloat>(std::cos(u))*p[0] +
            static_cast<IfcFloat>(entity.SemiAxis2)*static_cast<IfcFloat>(std::sin(u))*p[1];
    }

private:
    const IfcEllipse& entity;
};

// --------------------------------------------------------------------------------
// Line
// --------------------------------------------------------------------------------
class Line : public Curve {
public:
    // --------------------------------------------------
    Line(const IfcLine& entity, ConversionData& conv)
    : Curve(entity,conv) {
        ConvertCartesianPoint(p,entity.Pnt);
        ConvertVector(v,entity.Dir);
    }

    // --------------------------------------------------
    bool IsClosed() const {
        return false;
    }

    // --------------------------------------------------
    IfcVector3 Eval(IfcFloat u) const {
        return p + u*v;
    }

    // --------------------------------------------------
    size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
        ai_assert( InRange( a ) );
        ai_assert( InRange( b ) );
        // two points are always sufficient for a line segment
        return a==b ? 1 : 2;
    }


    // --------------------------------------------------
    void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const {
        ai_assert( InRange( a ) );
        ai_assert( InRange( b ) );

        if (a == b) {
            out.verts.push_back(Eval(a));
            return;
        }
        out.verts.reserve(out.verts.size()+2);
        out.verts.push_back(Eval(a));
        out.verts.push_back(Eval(b));
    }

    // --------------------------------------------------
    ParamRange GetParametricRange() const {
        const IfcFloat inf = std::numeric_limits<IfcFloat>::infinity();

        return std::make_pair(-inf,+inf);
    }

private:
    IfcVector3 p,v;
};

// --------------------------------------------------------------------------------
// CompositeCurve joins multiple smaller, bounded curves
// --------------------------------------------------------------------------------
class CompositeCurve : public BoundedCurve {
    typedef std::pair< std::shared_ptr< BoundedCurve >, bool > CurveEntry;

public:
    // --------------------------------------------------
    CompositeCurve(const IfcCompositeCurve& entity, ConversionData& conv)
    : BoundedCurve(entity,conv)
    , total() {
        curves.reserve(entity.Segments.size());
        for(const IfcCompositeCurveSegment& curveSegment :entity.Segments) {
            // according to the specification, this must be a bounded curve
            std::shared_ptr< Curve > cv(Curve::Convert(curveSegment.ParentCurve,conv));
            std::shared_ptr< BoundedCurve > bc = std::dynamic_pointer_cast<BoundedCurve>(cv);

            if (!bc) {
                IFCImporter::LogError("expected segment of composite curve to be a bounded curve");
                continue;
            }

            if ( (std::string)curveSegment.Transition != "CONTINUOUS" ) {
                IFCImporter::LogDebug("ignoring transition code on composite curve segment, only continuous transitions are supported");
            }

            curves.push_back( CurveEntry(bc,IsTrue(curveSegment.SameSense)) );
            total += bc->GetParametricRangeDelta();
        }

        if (curves.empty()) {
            throw CurveError("empty composite curve");
        }
    }

    // --------------------------------------------------
    IfcVector3 Eval(IfcFloat u) const {
        if (curves.empty()) {
            return IfcVector3();
        }

        IfcFloat acc = 0;
        for(const CurveEntry& entry : curves) {
            const ParamRange& range = entry.first->GetParametricRange();
            const IfcFloat delta = std::abs(range.second-range.first);
            if (u < acc+delta) {
                return entry.first->Eval( entry.second ? (u-acc) + range.first : range.second-(u-acc));
            }

            acc += delta;
        }
        // clamp to end
        return curves.back().first->Eval(curves.back().first->GetParametricRange().second);
    }

    // --------------------------------------------------
    size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
        ai_assert( InRange( a ) );
        ai_assert( InRange( b ) );
        size_t cnt = 0;

        IfcFloat acc = 0;
        for(const CurveEntry& entry : curves) {
            const ParamRange& range = entry.first->GetParametricRange();
            const IfcFloat delta = std::abs(range.second-range.first);
            if (a <= acc+delta && b >= acc) {
                const IfcFloat at =  std::max(static_cast<IfcFloat>( 0. ),a-acc), bt = std::min(delta,b-acc);
                cnt += entry.first->EstimateSampleCount( entry.second ? at + range.first : range.second - bt, entry.second ? bt + range.first : range.second - at );
            }

            acc += delta;
        }

        return cnt;
    }

    // --------------------------------------------------
    void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const {
        ai_assert( InRange( a ) );
        ai_assert( InRange( b ) );

        const size_t cnt = EstimateSampleCount(a,b);
        out.verts.reserve(out.verts.size() + cnt);

        for(const CurveEntry& entry : curves) {
            const size_t cnt = out.verts.size();
            entry.first->SampleDiscrete(out);

            if (!entry.second && cnt != out.verts.size()) {
                std::reverse(out.verts.begin()+cnt,out.verts.end());
            }
        }
    }

    // --------------------------------------------------
    ParamRange GetParametricRange() const {
        return std::make_pair(static_cast<IfcFloat>( 0. ),total);
    }

private:
    std::vector< CurveEntry > curves;
    IfcFloat total;
};

// --------------------------------------------------------------------------------
// TrimmedCurve can be used to trim an unbounded curve to a bounded range
// --------------------------------------------------------------------------------
class TrimmedCurve : public BoundedCurve {
public:
    // --------------------------------------------------
    TrimmedCurve(const IfcTrimmedCurve& entity, ConversionData& conv)
        : BoundedCurve(entity,conv)
    {
        base = std::shared_ptr<const Curve>(Curve::Convert(entity.BasisCurve,conv));

        typedef std::shared_ptr<const STEP::EXPRESS::DataType> Entry;

        // for some reason, trimmed curves can either specify a parametric value
        // or a point on the curve, or both. And they can even specify which of the
        // two representations they prefer, even though an information invariant
        // claims that they must be identical if both are present.
        // oh well.
        bool have_param = false, have_point = false;
        IfcVector3 point;
        for(const Entry sel :entity.Trim1) {
            if (const EXPRESS::REAL* const r = sel->ToPtr<EXPRESS::REAL>()) {
                range.first = *r;
                have_param = true;
                break;
            }
            else if (const IfcCartesianPoint* const r = sel->ResolveSelectPtr<IfcCartesianPoint>(conv.db)) {
                ConvertCartesianPoint(point,*r);
                have_point = true;
            }
        }
        if (!have_param) {
            if (!have_point || !base->ReverseEval(point,range.first)) {
                throw CurveError("IfcTrimmedCurve: failed to read first trim parameter, ignoring curve");
            }
        }
        have_param = false, have_point = false;
        for(const Entry sel :entity.Trim2) {
            if (const EXPRESS::REAL* const r = sel->ToPtr<EXPRESS::REAL>()) {
                range.second = *r;
                have_param = true;
                break;
            }
            else if (const IfcCartesianPoint* const r = sel->ResolveSelectPtr<IfcCartesianPoint>(conv.db)) {
                ConvertCartesianPoint(point,*r);
                have_point = true;
            }
        }
        if (!have_param) {
            if (!have_point || !base->ReverseEval(point,range.second)) {
                throw CurveError("IfcTrimmedCurve: failed to read second trim parameter, ignoring curve");
            }
        }

        agree_sense = IsTrue(entity.SenseAgreement);
        if( !agree_sense ) {
            std::swap(range.first,range.second);
        }

        // "NOTE In case of a closed curve, it may be necessary to increment t1 or t2
        // by the parametric length for consistency with the sense flag."
        if (base->IsClosed()) {
            if( range.first > range.second ) {
                range.second += base->GetParametricRangeDelta();
            }
        }

        maxval = range.second-range.first;
        ai_assert(maxval >= 0);
    }

    // --------------------------------------------------
    IfcVector3 Eval(IfcFloat p) const {
        ai_assert(InRange(p));
        return base->Eval( TrimParam(p) );
    }

    // --------------------------------------------------
    size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
        ai_assert( InRange( a ) );
        ai_assert( InRange( b ) );
        return base->EstimateSampleCount(TrimParam(a),TrimParam(b));
    }

    // --------------------------------------------------
    void SampleDiscrete(TempMesh& out,IfcFloat a,IfcFloat b) const {
        ai_assert(InRange(a) && InRange(b));
        return base->SampleDiscrete(out,TrimParam(a),TrimParam(b));
    }

    // --------------------------------------------------
    ParamRange GetParametricRange() const {
        return std::make_pair(static_cast<IfcFloat>( 0. ),maxval);
    }

private:
    // --------------------------------------------------
    IfcFloat TrimParam(IfcFloat f) const {
        return agree_sense ? f + range.first :  range.second - f;
    }

private:
    ParamRange range;
    IfcFloat maxval;
    bool agree_sense;

    std::shared_ptr<const Curve> base;
};


// --------------------------------------------------------------------------------
// PolyLine is a 'curve' defined by linear interpolation over a set of discrete points
// --------------------------------------------------------------------------------
class PolyLine : public BoundedCurve {
public:
    // --------------------------------------------------
    PolyLine(const IfcPolyline& entity, ConversionData& conv)
        : BoundedCurve(entity,conv)
    {
        points.reserve(entity.Points.size());

        IfcVector3 t;
        for(const IfcCartesianPoint& cp : entity.Points) {
            ConvertCartesianPoint(t,cp);
            points.push_back(t);
        }
    }

    // --------------------------------------------------
    IfcVector3 Eval(IfcFloat p) const {
        ai_assert(InRange(p));

        const size_t b = static_cast<size_t>(std::floor(p));
        if (b == points.size()-1) {
            return points.back();
        }

        const IfcFloat d = p-static_cast<IfcFloat>(b);
        return points[b+1] * d + points[b] * (static_cast<IfcFloat>( 1. )-d);
    }

    // --------------------------------------------------
    size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
        ai_assert(InRange(a) && InRange(b));
        return static_cast<size_t>( std::ceil(b) - std::floor(a) );
    }

    // --------------------------------------------------
    ParamRange GetParametricRange() const {
        return std::make_pair(static_cast<IfcFloat>( 0. ),static_cast<IfcFloat>(points.size()-1));
    }

private:
    std::vector<IfcVector3> points;
};

} // anon

// ------------------------------------------------------------------------------------------------
Curve* Curve::Convert(const IFC::IfcCurve& curve,ConversionData& conv) {
    if(curve.ToPtr<IfcBoundedCurve>()) {
        if(const IfcPolyline* c = curve.ToPtr<IfcPolyline>()) {
            return new PolyLine(*c,conv);
        }
        if(const IfcTrimmedCurve* c = curve.ToPtr<IfcTrimmedCurve>()) {
            return new TrimmedCurve(*c,conv);
        }
        if(const IfcCompositeCurve* c = curve.ToPtr<IfcCompositeCurve>()) {
            return new CompositeCurve(*c,conv);
        }
    }

    if(curve.ToPtr<IfcConic>()) {
        if(const IfcCircle* c = curve.ToPtr<IfcCircle>()) {
            return new Circle(*c,conv);
        }
        if(const IfcEllipse* c = curve.ToPtr<IfcEllipse>()) {
            return new Ellipse(*c,conv);
        }
    }

    if(const IfcLine* c = curve.ToPtr<IfcLine>()) {
        return new Line(*c,conv);
    }

    // XXX OffsetCurve2D, OffsetCurve3D not currently supported
    return NULL;
}

#ifdef ASSIMP_BUILD_DEBUG
// ------------------------------------------------------------------------------------------------
bool Curve::InRange(IfcFloat u) const {
    const ParamRange range = GetParametricRange();
    if (IsClosed()) {
        return true;
    }
    const IfcFloat epsilon = 1e-5;
    return u - range.first > -epsilon && range.second - u > -epsilon;
}
#endif

// ------------------------------------------------------------------------------------------------
IfcFloat Curve::GetParametricRangeDelta() const {
    const ParamRange& range = GetParametricRange();
    return std::abs(range.second - range.first);
}

// ------------------------------------------------------------------------------------------------
size_t Curve::EstimateSampleCount(IfcFloat a, IfcFloat b) const {
    (void)(a); (void)(b);  
    ai_assert( InRange( a ) );
    ai_assert( InRange( b ) );

    // arbitrary default value, deriving classes should supply better suited values
    return 16;
}

// ------------------------------------------------------------------------------------------------
IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, IfcFloat b,
        unsigned int samples, IfcFloat threshold, unsigned int recurse = 0, unsigned int max_recurse = 15) {
    ai_assert(samples>1);

    const IfcFloat delta = (b-a)/samples, inf = std::numeric_limits<IfcFloat>::infinity();
    IfcFloat min_point[2] = {a,b}, min_diff[2] = {inf,inf};
    IfcFloat runner = a;

    for (unsigned int i = 0; i < samples; ++i, runner += delta) {
        const IfcFloat diff = (cv->Eval(runner)-val).SquareLength();
        if (diff < min_diff[0]) {
            min_diff[1] = min_diff[0];
            min_point[1] = min_point[0];

            min_diff[0] = diff;
            min_point[0] = runner;
        }
        else if (diff < min_diff[1]) {
            min_diff[1] = diff;
            min_point[1] = runner;
        }
    }

    ai_assert( min_diff[ 0 ] != inf );
    ai_assert( min_diff[ 1 ] != inf );
    if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
        return min_point[0];
    }

    // fix for closed curves to take their wrap-over into account
    if (cv->IsClosed() && std::fabs(min_point[0]-min_point[1]) > cv->GetParametricRangeDelta()*0.5  ) {
        const Curve::ParamRange& range = cv->GetParametricRange();
        const IfcFloat wrapdiff = (cv->Eval(range.first)-val).SquareLength();

        if (wrapdiff < min_diff[0]) {
            const IfcFloat t = min_point[0];
            min_point[0] = min_point[1] > min_point[0] ? range.first : range.second;
             min_point[1] = t;
        }
    }

    return RecursiveSearch(cv,val,min_point[0],min_point[1],samples,threshold,recurse+1,max_recurse);
}

// ------------------------------------------------------------------------------------------------
bool Curve::ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const
{
    // note: the following algorithm is not guaranteed to find the 'right' parameter value
    // in all possible cases, but it will always return at least some value so this function
    // will never fail in the default implementation.

    // XXX derive threshold from curve topology
    static const IfcFloat threshold = 1e-4f;
    static const unsigned int samples = 16;

    const ParamRange& range = GetParametricRange();
    paramOut = RecursiveSearch(this,val,range.first,range.second,samples,threshold);

    return true;
}

// ------------------------------------------------------------------------------------------------
void Curve::SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const {
    ai_assert( InRange( a ) );
    ai_assert( InRange( b ) );

    const size_t cnt = std::max(static_cast<size_t>(0),EstimateSampleCount(a,b));
    out.verts.reserve( out.verts.size() + cnt + 1);

    IfcFloat p = a, delta = (b-a)/cnt;
    for(size_t i = 0; i <= cnt; ++i, p += delta) {
        out.verts.push_back(Eval(p));
    }
}

// ------------------------------------------------------------------------------------------------
bool BoundedCurve::IsClosed() const {
    return false;
}

// ------------------------------------------------------------------------------------------------
void BoundedCurve::SampleDiscrete(TempMesh& out) const {
    const ParamRange& range = GetParametricRange();
    ai_assert( range.first != std::numeric_limits<IfcFloat>::infinity() );
    ai_assert( range.second != std::numeric_limits<IfcFloat>::infinity() );

    return SampleDiscrete(out,range.first,range.second);
}

} // IFC
} // Assimp

#endif // ASSIMP_BUILD_NO_IFC_IMPORTER
