/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_
#define LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_

#include "dsp/core/basic.h"

//#define LOG_NDEBUG 0
#include <cutils/log.h>


namespace le_fx {

namespace sigmod {

template <typename T, class Algorithm>
InterpolatorBase<T, Algorithm>::InterpolatorBase() {
  status_ = false;
  cached_index_ = 0;
  x_data_ = NULL;
  y_data_ = NULL;
  data_length_ = 0;
  own_x_data_ = false;
  x_start_offset_ = 0.0;
  last_element_index_ = -1;
  x_inverse_sampling_interval_ = 0.0;
  state_ = NULL;
}

template <typename T, class Algorithm>
InterpolatorBase<T, Algorithm>::~InterpolatorBase() {
  delete [] state_;
  if (own_x_data_) {
    delete [] x_data_;
  }
}

template <typename T, class Algorithm>
bool InterpolatorBase<T, Algorithm>::Initialize(const vector<T> &x_data,
                                                const vector<T> &y_data) {
#ifndef NDEBUG
  if (x_data.size() != y_data.size()) {
    LoggerError("InterpolatorBase::Initialize: xData size (%d) != yData size"
                  " (%d)", x_data.size(), y_data.size());
  }
#endif
  return Initialize(&x_data[0], &y_data[0], x_data.size());
}

template <typename T, class Algorithm>
bool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset,
                                                double x_sampling_interval,
                                                const vector<T> &y_data) {
  return Initialize(x_start_offset,
                    x_sampling_interval,
                    &y_data[0],
                    y_data.size());
}

template <typename T, class Algorithm>
bool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset,
                                                double x_sampling_interval,
                                                const T *y_data,
                                                int data_length) {
  // Constructs and populate x-axis data: `x_data_`
  T *x_data_tmp = new T[data_length];
  float time_offset = x_start_offset;
  for (int n = 0; n < data_length; n++) {
    x_data_tmp[n] = time_offset;
    time_offset += x_sampling_interval;
  }
  Initialize(x_data_tmp, y_data, data_length);
  // Sets-up the regularly sampled interpolation mode
  x_start_offset_ = x_start_offset;
  x_inverse_sampling_interval_ = 1.0 / x_sampling_interval;
  own_x_data_ = true;
  return status_;
}


template <typename T, class Algorithm>
bool InterpolatorBase<T, Algorithm>::Initialize(
    const T *x_data, const T *y_data, int data_length) {
  // Default settings
  cached_index_ = 0;
  data_length_ = 0;
  x_start_offset_ = 0;
  x_inverse_sampling_interval_ = 0;
  state_ = NULL;
  // Input data is externally owned
  own_x_data_ = false;
  x_data_ = x_data;
  y_data_ = y_data;
  data_length_ = data_length;
  last_element_index_ = data_length - 1;
  // Check input data sanity
  for (int n = 0; n < last_element_index_; ++n) {
    if (x_data_[n + 1] <= x_data_[n]) {
      ALOGE("InterpolatorBase::Initialize: xData are not ordered or "
              "contain equal values (X[%d] <= X[%d]) (%.5e <= %.5e)",
              n + 1, n, x_data_[n + 1], x_data_[n]);
      status_ = false;
      return false;
    }
  }
  // Pre-compute internal state by calling the corresponding function of the
  // derived class.
  status_ = static_cast<Algorithm*>(this)->SetInternalState();
  return status_;
}

template <typename T, class Algorithm>
T InterpolatorBase<T, Algorithm>::Interpolate(T x) {
#ifndef NDEBUG
  if (cached_index_ < 0 || cached_index_ > data_length_ - 2) {
    LoggerError("InterpolatorBase:Interpolate: CachedIndex_ out of bounds "
                  "[0, %d, %d]", cached_index_, data_length_ - 2);
  }
#endif
  // Search for the containing interval
  if (x <= x_data_[cached_index_]) {
    if (cached_index_ <= 0) {
      cached_index_ = 0;
      return y_data_[0];
    }
    if (x >= x_data_[cached_index_ - 1]) {
      cached_index_--;  // Fast descending
    } else {
      if (x <= x_data_[0]) {
        cached_index_ = 0;
        return y_data_[0];
      }
      cached_index_ = SearchIndex(x_data_, x, 0, cached_index_);
    }
  } else {
    if (cached_index_ >= last_element_index_) {
      cached_index_ = last_element_index_;
      return y_data_[last_element_index_];
    }
    if (x > x_data_[cached_index_ + 1]) {
      if (cached_index_ + 2 > last_element_index_) {
        cached_index_ = last_element_index_ - 1;
        return y_data_[last_element_index_];
      }
      if (x <= x_data_[cached_index_ + 2]) {
        cached_index_++;  // Fast ascending
      } else {
        if (x >= x_data_[last_element_index_]) {
          cached_index_ = last_element_index_ - 1;
          return y_data_[last_element_index_];
        }
        cached_index_ = SearchIndex(
            x_data_, x, cached_index_, last_element_index_);
      }
    }
  }
  // Compute interpolated value by calling the corresponding function of the
  // derived class.
  return static_cast<Algorithm*>(this)->MethodSpecificInterpolation(x);
}

}  // namespace sigmod

}  // namespace le_fx

#endif  // LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_
