/* -*- c++ -*- */
/* @file
 * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
 * @section LICENSE
 * 
 * Gr-gsm 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 3, or (at your option)
 * any later version.
 * 
 * Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 * 
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gnuradio/io_signature.h>
#include "controlled_fractional_resampler_cc_impl.h"
#include <stdexcept>

namespace gr {
  namespace gsm {

    controlled_fractional_resampler_cc::sptr
    controlled_fractional_resampler_cc::make(float phase_shift, float resamp_ratio)
    {
      return gnuradio::get_initial_sptr
        (new controlled_fractional_resampler_cc_impl(phase_shift, resamp_ratio));
    }

    controlled_fractional_resampler_cc_impl::controlled_fractional_resampler_cc_impl
                                     (float phase_shift, float resamp_ratio)
      : block("controlled_fractional_resampler_cc",
              io_signature::make(1, 1, sizeof(gr_complex)),
              io_signature::make(1, 1, sizeof(gr_complex))),
        d_mu(phase_shift), d_mu_inc(resamp_ratio),
        d_resamp(new mmse_fir_interpolator_cc()),
        d_last_original_offset(0)
    {
      this->set_tag_propagation_policy(TPP_DONT);
      if(resamp_ratio <=  0)
        throw std::out_of_range("resampling ratio must be > 0");
      if(phase_shift <  0  || phase_shift > 1)
        throw std::out_of_range("phase shift ratio must be > 0 and < 1");

      set_relative_rate(1.0 / resamp_ratio);
    }

    controlled_fractional_resampler_cc_impl::~controlled_fractional_resampler_cc_impl()
    {
      delete d_resamp;
    }

    void
    controlled_fractional_resampler_cc_impl::forecast(int noutput_items,
                                           gr_vector_int &ninput_items_required)
    {
      unsigned ninputs = ninput_items_required.size();
      for(unsigned i=0; i < ninputs; i++) {
        ninput_items_required[i] =
          (int)ceil((noutput_items * d_mu_inc) + d_resamp->ntaps());
      }
    }

    int
    controlled_fractional_resampler_cc_impl::general_work(int noutput_items,
                                               gr_vector_int &ninput_items,
                                               gr_vector_const_void_star &input_items,
                                               gr_vector_void_star &output_items)
    {
      const gr_complex *in = (const gr_complex*)input_items[0];
      gr_complex *out = (gr_complex*)output_items[0];

      uint64_t processed_in = 0; //input samples processed in the last call to resample function
      uint64_t processed_in_sum = 0; //input samples processed during a whole call to general_work function
      uint64_t produced_out_sum = 0; //output samples produced during a whole call to general_work function

      std::vector<tag_t> tags;

      pmt::pmt_t key = pmt::string_to_symbol("set_resamp_ratio");
      get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+ninput_items[0]);

      bool out_buffer_full = false;
      for(std::vector<tag_t>::iterator i_tag = tags.begin(); i_tag != tags.end(); i_tag++)
      {
        uint64_t tag_offset_rel = i_tag->offset - nitems_read(0);

        if(pmt::symbol_to_string(i_tag->key) == "set_resamp_ratio")
        {
          uint64_t samples_to_produce = static_cast<uint64_t>(round(static_cast<double>(tag_offset_rel-processed_in_sum)/d_mu_inc));

          if((samples_to_produce + produced_out_sum) > noutput_items)
          {
            samples_to_produce = noutput_items - produced_out_sum;
            out_buffer_full = true;
          }

          processed_in = resample(in, processed_in_sum, out, produced_out_sum, samples_to_produce);
          processed_in_sum = processed_in_sum + processed_in;
          produced_out_sum = produced_out_sum + samples_to_produce;

          if(out_buffer_full)
          {
            break;
          } else {
            set_resamp_ratio(pmt::to_double(i_tag->value));
            tag_t original_offset_tag;
            uint64_t offset = produced_out_sum + nitems_written(0);
            if(d_last_original_offset != offset){ //prevent from sending multiple "original_offset" tags for the same offset
              add_item_tag(0, offset, pmt::mp("original_offset"), pmt::from_uint64(i_tag->offset));
              d_last_original_offset = offset;
            }
            add_item_tag(0, offset, i_tag->key, i_tag->value);
          }
        } else {
          uint64_t out_samples_to_tag = round(static_cast<double>(tag_offset_rel-processed_in_sum)/d_mu_inc);
          if( (out_samples_to_tag + produced_out_sum) < noutput_items)
          {
            uint64_t offset = produced_out_sum + out_samples_to_tag + nitems_written(0);
            if(d_last_original_offset != offset){
              add_item_tag(0, offset, pmt::mp("original_offset"), pmt::from_uint64(i_tag->offset));
              d_last_original_offset = offset;
            }
            add_item_tag(0, offset, i_tag->key, i_tag->value);
          }
        }
      }

      if(!out_buffer_full)
      {
        processed_in = resample(in, processed_in_sum, out, produced_out_sum, (noutput_items-produced_out_sum));
        processed_in_sum = processed_in_sum + processed_in;
      }

      consume_each(processed_in_sum);
      return noutput_items;
    }

    inline uint64_t 
    controlled_fractional_resampler_cc_impl::resample(const gr_complex *in, uint64_t first_in_sample, gr_complex *out, uint64_t first_out_sample, uint64_t samples_to_produce)
    {
      int ii = first_in_sample;
      int oo = first_out_sample;
      while(oo < (first_out_sample+samples_to_produce)) //produce samples_to_produce number of samples
      {
        out[oo++] = d_resamp->interpolate(&in[ii], d_mu);

        double s = d_mu + d_mu_inc;
        double f = floor(s);
        int incr = (int)f;
        d_mu = s - f;
        ii += incr;
      }
      return ii-first_in_sample; //number of input samples processed
    }

    float
    controlled_fractional_resampler_cc_impl::mu() const
    {
      return d_mu;
    }

    float
    controlled_fractional_resampler_cc_impl::resamp_ratio() const
    {
      return d_mu_inc;
    }

    void
    controlled_fractional_resampler_cc_impl::set_mu(float mu)
    {
      d_mu = mu;
    }

    void
    controlled_fractional_resampler_cc_impl::set_resamp_ratio(float resamp_ratio)
    {
      d_mu_inc = resamp_ratio;
      set_relative_rate(1.0 / resamp_ratio);
    }

  } /* namespace gsm */
} /* namespace gr */

