from typing import Optional, Collection, Tuple

import numpy as np

from .histogram1d import Histogram1D
from .binnings import BinningBase
from .plotting import PlottingProxy


class HistogramCollection(Collection[Histogram1D]):
    """Experimental collection of histograms."""
    def __init__(self,
                 *histograms: Histogram1D,
                 binning: Optional[BinningBase] = None,
                 title: Optional[str] = None,
                 name: Optional[str] = None):
        self.histograms = list(histograms)
        if histograms:
            if binning:
                raise ValueError("")
            self._binning = histograms[0].binning
            if not all(h.binning == self._binning for h in histograms):
                raise ValueError("All histogram should share the same binning.")
        else:
            self._binning = binning
        self.name = name
        self.title = title or self.name

    def __contains__(self, item):
        try:
            _ = self[item]
            return True
        except KeyError:
            return False

    @property
    def ndim(self) -> int:
        return 1

    def __iter__(self):
        return iter(self.histograms)

    def __len__(self):
        return len(self.histograms)

    @property
    def binning(self) -> BinningBase:
        return self._binning

    @property
    def bins(self) -> np.ndarray:
        return self.binning.bins

    @property
    def axis_name(self) ->  Optional[str]:
        return self.histograms and self.histograms[0].axis_name or None

    @property
    def axis_names(self) -> Tuple[str]:
        return (self.axis_name,)

    def add(self, histogram: Histogram1D):
        if not self.binning == histogram.binning:
            raise ValueError("Cannot add histogram with different binning.")
        self.histograms.append(histogram)

    def create(self, name: str, values, *, weights=None, dropna: bool = True, **kwargs):
        init_kwargs = {
            "axis_name": self.axis_name
        }
        init_kwargs.update(kwargs)
        histogram = Histogram1D(binning=self.binning, name=name, **init_kwargs)
        histogram.fill_n(values, weights=weights, dropna=dropna)
        self.histograms.append(histogram)
        return histogram

    def __getitem__(self, item) -> Histogram1D:
        if isinstance(item, str):
            candidates = [h for h in self.histograms if h.name == item]
            if len(candidates) == 0:
                raise KeyError("Collection does not contain histogram named {0}".format(item))
            return candidates[0]
        else:
            return self.histograms[item]

    @property
    def plot(self) -> PlottingProxy:
        return PlottingProxy(self)

@@ -39,17 +39,28 @@
 n, Tuple
+, Dict, Any
 %0A
-
 %0Aimport 
@@ -180,16 +180,34 @@
 gProxy%0A%0A
+from . import h1%0A%0A
 %0Aclass H
@@ -1653,17 +1653,16 @@
  return 
-(
 self.axi
@@ -1668,17 +1668,16 @@
 is_name,
-)
 %0A%0A    de
@@ -2720,16 +2720,16 @@
 gProxy:%0A
-
         
@@ -2755,8 +2755,511 @@
 y(self)%0A
+%0A    @classmethod%0A    def h1(cls, a_dict: Dict%5Bstr, Any%5D, bins=None, **kwargs) -%3E %22HistogramCollection%22:%0A        mega_values = np.concatenate(list(a_dict.values()))%0A        binning = h1(mega_values, bins, **kwargs).binning%0A%0A        title = kwargs.pop(%22title%22, None)%0A        name = kwargs.pop(%22name%22, None)%0A%0A        collection = HistogramCollection(binning=binning, title=title, name=name)%0A        for key, value in a_dict.items():%0A            collection.create(key, value)%0A        return collection%0A%0A%0A%0A%0A

Create HistogramCollection from collection of data