#     Copyright 2016-present CERN – European Organization for Nuclear Research
#
#     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.
from qf_lib.backtesting.order.execution_style import ExecutionStyle
from qf_lib.backtesting.order.time_in_force import TimeInForce
from qf_lib.common.tickers.tickers import Ticker


class Order:
    """
    Order generated by a strategy, then processed by PositionSizer.
    Finally executed by ExecutionHandler.
    """

    def __init__(self, ticker: Ticker, quantity: float, execution_style: ExecutionStyle,
                 time_in_force: TimeInForce, order_state: str = "", strategy: str = ""):
        """
        This __init__ shouldn't be used anywhere beyond this module. Use OrderFactory for creating Order objects.
        """
        self.id = None  # type:int
        self.ticker = ticker
        self.quantity = quantity
        self.time_in_force = time_in_force
        self.execution_style = execution_style
        self.order_state = order_state
        self.strategy = strategy

    def __str__(self):
        return f"\nOrder:\n" \
               f"\tid: {self.id}\n" \
               f"\tticker: {self.ticker}\n" \
               f"\tquantity: {self.quantity}\n" \
               f"\ttif: {self.time_in_force}\n" \
               f"\texecution_style: {self.execution_style}\n" \
               f"\torder_state: {self.order_state}\n" \
               f"\tstrategy: {self.strategy}"

    def __eq__(self, other):
        if self is other:
            return True

        if not isinstance(other, Order):
            return False

        if self.id is not None and other.id == self.id:
            return True

        # when both ids are none -> compare the values
        return (self.ticker, self.quantity, self.time_in_force, self.execution_style) == \
               (other.ticker, other.quantity, other.time_in_force, other.execution_style)

    def __hash__(self):
        return hash((self.ticker, self.quantity, self.time_in_force, self.execution_style))
