// Copyright 2019 Bloomberg Finance L.P
//
// 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 INCLUDED_BUILDBOXCOMMONMETRICS_METRICCOLLECTORFACTORY_H
#define INCLUDED_BUILDBOXCOMMONMETRICS_METRICCOLLECTORFACTORY_H

#include <string>
#include <typeinfo>
#include <unordered_map>

#include <buildboxcommonmetrics_metriccollector.h>

namespace buildboxcommon {
namespace buildboxcommonmetrics {
/**
 * MetricCollectorFactory
 *
 * Singleton to manage static MetricCollectors of various types <ValueType>
 */
class MetricCollectorFactory {
  private:
    // Flag to indicate whether metrics are globally enabled.
    // Default to true.
    bool d_metricsEnabled = true;
    // Prefix to prepend to metric names
    std::string d_metricPrefix = "";

    // Constructor
    MetricCollectorFactory() {};
    // Delete Copy Constructor
    MetricCollectorFactory(MetricCollectorFactory const &) = delete;
    // Destructor
    ~MetricCollectorFactory() {};
    // Delete Assignment operator
    MetricCollectorFactory &operator=(MetricCollectorFactory const &) = delete;
    // Delete Move Constructor
    MetricCollectorFactory(MetricCollectorFactory &&) = delete;
    // Delete Move Assignment operator
    MetricCollectorFactory &operator=(MetricCollectorFactory &&) = delete;

  public:
    // Singleton Instance accessor
    static MetricCollectorFactory *getInstance();

    // Singleton Instance Accessor Template for each ValueType
    template <typename ValueType>
    static MetricCollector<ValueType> *getCollector()
    {
        static MetricCollector<ValueType> collector;
        return &collector;
    }

    // These manipulators and accessors are not thread-safe: the enablement and
    // disablement of metrics should be done at process start time.
    // MANIPULATORS
    void setMetricsEnabled(const bool enabled);
    void setMetricsPrefix(const std::string &prefix);
    void enableMetrics();
    void disableMetrics();

    // ACCESSORS
    bool metricsEnabled() const;
    const std::string &metricsPrefix() const;
};

} // namespace buildboxcommonmetrics
} // namespace buildboxcommon
#endif
