from collections import Sequence

from typing import Any, Optional, Callable, Iterable, Dict, Union

from . import data_types as data_types
from .data_types import (
    Text as Text,
    Number as Number,
    Boolean as Boolean,
    DateTime as DateTime,
    Date as Date,
    TimeDelta as TimeDelta,
)


class MappedSequence(Sequence):
    def __init__(self, values: Any, keys: Optional[Any] = ...) -> None: ...
    def __unicode__(self): ...
    def __getitem__(self, key: Any): ...
    def __setitem__(self, key: Any, value: Any) -> None: ...
    def __iter__(self): ...
    def __len__(self): ...
    def __eq__(self, other: Any): ...
    def __ne__(self, other: Any): ...
    def __contains__(self, value: Any): ...
    def keys(self): ...
    def values(self): ...
    def items(self): ...
    def get(self, key: Any, default: Optional[Any] = ...): ...
    def dict(self): ...


class Row(MappedSequence): ...


class Table:
    def __init__(self, rows: Any, column_names: Optional[Any] = ..., column_types: Optional[Any] = ..., row_names: Optional[Any] = ..., _is_fork: bool = ...) -> None: ...
    def __len__(self): ...
    def __iter__(self): ...
    def __getitem__(self, key: Any): ...
    @property
    def column_types(self): ...
    @property
    def column_names(self): ...
    @property
    def row_names(self): ...
    @property
    def columns(self): ...
    @property
    def rows(self): ...
    def print_csv(self, **kwargs: Any) -> None: ...
    def print_json(self, **kwargs: Any) -> None: ...
    def where(self, test: Callable[[Row], bool]) -> 'Table': ...
    def select(self, key: Union[Iterable[str], str]) -> 'Table': ...
    # these definitions are much narrower than what's actually accepted
    @classmethod
    def from_object(cls, obj: Iterable[Dict[str, Any]], *, column_types: Optional['TypeTester'] = None) -> 'Table': ...
    @classmethod
    def from_csv(cls, path: Iterable[str], *, column_types: Optional['TypeTester'] = None) -> 'Table': ...
    @classmethod
    def merge(cls, tables: Iterable['Table']) -> 'Table': ...
    def rename(self, column_names: Optional[Iterable[str]] = None, row_names: Optional[Any] = None, slug_columns: bool = False, slug_rows: bool=False, **kwargs: Any) -> 'Table': ...


class TypeTester:
    def __init__(self, force: Any = ..., limit: Optional[Any] = ..., types: Optional[Any] = ...) -> None: ...
    def run(self, rows: Any, column_names: Any): ...


class MaxPrecision:
    def __init__(self, column_name: Any) -> None: ...


# this is not strictly true, but it's all we care about.
def aggregate(self, aggregations: MaxPrecision) -> int: ...
