
#include <AMReX_MFCopyDescriptor.H>

namespace amrex {

void
InterpAddBox (MultiFabCopyDescriptor& fabCopyDesc,
              BoxList*                returnUnfilledBoxes,
              Vector<FillBoxId>&       returnedFillBoxIds,
              const Box&              subbox,
              MultiFabId              faid1,
              MultiFabId              faid2,
              Real                    t1,
              Real                    t2,
              Real                    t,
              int                     src_comp,
              int                     dest_comp,
              int                     num_comp,
              bool                    extrap)
{
    amrex::ignore_unused(extrap);

    const Real teps = (t2-t1)/1000.0_rt;

    BL_ASSERT(extrap || ( (t>=t1-teps) && (t <= t2+teps) ) );

    if (t >= t1-teps && t <= t1+teps)
    {
        returnedFillBoxIds.resize(1);
        returnedFillBoxIds[0] = fabCopyDesc.AddBox(faid1,
                                                   subbox,
                                                   returnUnfilledBoxes,
                                                   src_comp,
                                                   dest_comp,
                                                   num_comp);
    }
    else if (t > t2-teps && t < t2+teps)
    {
        returnedFillBoxIds.resize(1);
        returnedFillBoxIds[0] = fabCopyDesc.AddBox(faid2,
                                                   subbox,
                                                   returnUnfilledBoxes,
                                                   src_comp,
                                                   dest_comp,
                                                   num_comp);
    }
    else
    {
        returnedFillBoxIds.resize(2);
        BoxList tempUnfilledBoxes(subbox.ixType());
        returnedFillBoxIds[0] = fabCopyDesc.AddBox(faid1,
                                                   subbox,
                                                   returnUnfilledBoxes,
                                                   src_comp,
                                                   dest_comp,
                                                   num_comp);
        returnedFillBoxIds[1] = fabCopyDesc.AddBox(faid2,
                                                   subbox,
                                                   &tempUnfilledBoxes,
                                                   src_comp,
                                                   dest_comp,
                                                   num_comp);
        //
        // The boxarrays for faid1 and faid2 should be the
        // same so only use returnUnfilledBoxes from one AddBox here.
        //
    }
}

void
InterpFillFab (MultiFabCopyDescriptor& fabCopyDesc,
               const Vector<FillBoxId>& fillBoxIds,
               MultiFabId              faid1,
               MultiFabId              faid2,
               FArrayBox&              dest,
               Real                    t1,
               Real                    t2,
               Real                    t,
               int                     src_comp,   // these comps need to be removed
               int                     dest_comp,  // from this routine
               int                     num_comp,
               bool                    extrap)
{
    amrex::ignore_unused(extrap);

    const Real teps = (t2-t1)/1000.0_rt;

    BL_ASSERT(extrap || ( (t>=t1-teps) && (t <= t2+teps) ) );

    if (t >= t1-teps && t <= t1+teps)
    {
        fabCopyDesc.FillFab(faid1, fillBoxIds[0], dest);
    }
    else if (t > t2-teps && t < t2+teps)
    {
        fabCopyDesc.FillFab(faid2, fillBoxIds[0], dest);
    }
    else
    {
        BL_ASSERT(dest_comp + num_comp <= dest.nComp());

        FArrayBox dest1(dest.box(), dest.nComp());
        dest1.setVal<RunOn::Host>(std::numeric_limits<Real>::quiet_NaN());
        FArrayBox dest2(dest.box(), dest.nComp());
        dest2.setVal<RunOn::Host>(std::numeric_limits<Real>::quiet_NaN());
        fabCopyDesc.FillFab(faid1, fillBoxIds[0], dest1);
        fabCopyDesc.FillFab(faid2, fillBoxIds[1], dest2);
        dest.linInterp<RunOn::Host>
                      (dest1,
                       src_comp,
                       dest2,
                       src_comp,
                       t1,
                       t2,
                       t,
                       dest.box(),
                       dest_comp,
                       num_comp);
    }
}

}
