from abc import ABCMeta, abstractmethod
from xml.etree import cElementTree

from ._Order import Order  # noqa
from typing import (
    Any,
    Dict,
    List,
    Optional,
    Union,
)
from ._Table import Table  # noqa


class TableService(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def list_tables(self, pos_id):
        # type: (Union[int, str]) -> List[Table]
        raise NotImplementedError()

    @abstractmethod
    def start_service(self, pos_id, table_id, seats, tab_id="", mode="", source_table_id=""):
        # type: (Union[int, str], str, int, Optional[str], Optional[str], Optional[str]) -> str
        raise NotImplementedError()

    @abstractmethod
    def recall_service(self, pos_id, table_id):
        # type: (Union[int, str], str) -> str
        raise NotImplementedError()

    @abstractmethod
    def store_service(self, pos_id, table_id):
        # type: (Union[int, str], str) -> bool
        raise NotImplementedError()

    @abstractmethod
    def create_order(
        self,
        pos_id,                 # type: Union[int, str]
        table_id,               # type: str
        custom_properties,      # type: str
    ):
        # type: (...) -> None

        raise NotImplementedError()

    @abstractmethod
    def get_table_picture(self, pos_id, table_id):
        # type: (Union[int, str], str) -> str
        raise NotImplementedError()

    @abstractmethod
    def get_selected_table(self, pos_id):
        # type: (Union[int, str]) -> Table
        raise NotImplementedError()

    @abstractmethod
    def get_table_info(self, pos_id, table_id):
        # type: (Union[int, str], str) -> str
        raise NotImplementedError()

    @abstractmethod
    def do_total_table(self, pos_id, table_id, tip_rate=None, selected_to_total=None):
        # type: (Union[int, str], str, Optional[str], Optional[str]) -> str
        raise NotImplementedError()

    @abstractmethod
    def reopen_table(self, pos_id, table_id):
        # type: (Union[int, str], str) -> str
        raise NotImplementedError()

    @abstractmethod
    def close_table(
        self,           # type: TableService
        pos_id,         # type: str
        table_id,       # type: str
        user_id,        # type: str
    ):
        # type: (...) -> str

        raise NotImplementedError()

    @abstractmethod
    def set_table_available(self, pos_id, table_id):
        # type: (Union[int, str], str) -> None
        raise NotImplementedError()

    @abstractmethod
    def get_current_table_id(self, pos_id):
        # type: (Union[int, str]) -> str
        raise NotImplementedError()

    @abstractmethod
    def clear_service_tenders(self, pos_id, table_id):
        # type: (Union[int, str], str) -> str
        raise NotImplementedError()

    @abstractmethod
    def change_service_tip(self, pos_id, table_id, percentage=None, amount=None):
        # type: (Union[int, str], str, Optional[str], Optional[str]) -> str
        raise NotImplementedError()

    @abstractmethod
    def register_service_tender(
        self,                   # type: TableService
        pos_id,                 # type: str
        user_id,                # type: str
        table_id,               # type: str
        tender_id,              # type: int
        amount,                 # type: Any[float, str]
        tender_details="",      # type: str
    ):
        # type: (...) -> str

        raise NotImplementedError()

    @abstractmethod
    def get_table_orders(self, pos_id, table_id):
        # type: (Union[int, str], str) -> List[Order]
        raise NotImplementedError()

    @abstractmethod
    def set_parent_table(
        self,
        pos_id,             # type: str
        table_id,           # type: str
        parent_table_id,    # type: str
    ):
        # type: (...) -> None

        raise NotImplementedError()

    @abstractmethod
    def set_current_order(
        self,
        pos_id,     # type: Any[Union[str, int]]
        order_id,   # type: str
        table_id    # type: str
    ):
        # type: (...) -> None

        raise NotImplementedError()

    @abstractmethod
    def get_service_seats_count(self, table_info_xml):
        # type: (cElementTree.XML) -> int
        raise NotImplementedError()

    @abstractmethod
    def set_sale_line_seat(self, pos_id, seat_number, order_id, line_number, item_id, level, part_code):
        # type: (Union[int, str], int, str, str, str, str, str) -> None
        raise NotImplementedError()

    @abstractmethod
    def get_sectors(
        self,
        pos_id,     # type: Any[Union[str, int]]
    ):
        # type: (...) -> List[str]

        raise NotImplementedError()

    @abstractmethod
    def get_operator_sector_info(
        self,
        pos_id,     # type: Any[Union[str, int]]
    ):
        # type: (...) -> List[str]

        raise NotImplementedError()

    @abstractmethod
    def update_operator_sector_info(
        self,
        pos_id,         # type: Any[Union[str, int]]
        update_info,    # type: Dict[str, Dict]
    ):
        # type: (...) -> List[str]

        raise NotImplementedError()

    @abstractmethod
    def set_table_custom_property(
        self,
        pos_id,  # type: Any[Union[str, int]]
        prop,           # type: str
        prop_value,     # type: str
        table_id,       # type: str
        service_id,     # type: int
    ):
        # type: (...) -> None

        raise NotImplementedError()

    @abstractmethod
    def set_table_custom_properties(
        self,
        pos_id,         # type: Any[Union[str, int]]
        properties,     # type: str
        table_id,       # type: str
        service_id,     # type: int
    ):
        # type: (...) -> None

        raise NotImplementedError()
