/*
    libmaus2
    Copyright (C) 2019 German Tischler-Höhle

    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 3 of the License, or
    (at your option) any later version.

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#if ! defined(LIBMAUS2_MATH_HISTOGRAMBUCKETS_HPP)
#define LIBMAUS2_MATH_HISTOGRAMBUCKETS_HPP

#include <libmaus2/autoarray/AutoArray.hpp>

namespace libmaus2
{
	namespace math
	{
		struct HistogramBuckets
		{
			typedef std::map<int64_t,uint64_t>::const_iterator const_iterator;

			double const bucketsize;
			std::map<int64_t,uint64_t> M;
			uint64_t n;

			HistogramBuckets(double const rbucketsize, std::vector<double> const & V)
			: bucketsize(rbucketsize), M(), n(0)
			{
				for ( uint64_t i = 0; i < V.size(); ++i )
				{
					double const v = V[i];
					uint64_t const bucketid = static_cast<uint64_t>( (v + bucketsize/2.0) / bucketsize );
					M[bucketid]++;
					n += 1;
				}
			}

			double getBucketCentre(int64_t const i) const
			{
				return i * bucketsize;
			}

			const_iterator begin() const
			{
				return M.begin();
			}

			const_iterator end() const
			{
				return M.end();
			}

			std::pair<
				libmaus2::autoarray::AutoArray<double>::shared_ptr_type,
				libmaus2::autoarray::AutoArray<double>::shared_ptr_type
			> getArrays() const
			{
				double const dn = n;
				double const f = 1.0 / dn;
				double s = 0;

				libmaus2::autoarray::AutoArray<double>::shared_ptr_type A_X(new libmaus2::autoarray::AutoArray<double>);
				libmaus2::autoarray::AutoArray<double>::shared_ptr_type A_Y(new libmaus2::autoarray::AutoArray<double>);

				uint64_t o_X = 0;
				uint64_t o_Y = 0;

				for ( const_iterator it = begin(); it != end(); ++it )
				{
					double const x = getBucketCentre(it->first);
					double const y = it->second * f;

					A_X->push(o_X,x);
					A_Y->push(o_Y,y);

					s += y;
				}

				assert ( o_X == o_Y );

				A_X->resize(o_X);
				A_Y->resize(o_Y);

				return
					std::pair<
						libmaus2::autoarray::AutoArray<double>::shared_ptr_type,
						libmaus2::autoarray::AutoArray<double>::shared_ptr_type
					>(
						A_X,A_Y
					);
			}
		};
	}
}
#endif
