# Path: openprocurement/tender/openua/utils.py
# def calculate_normalized_date(dt, tender, ceil=False):
#     if (tender.revisions[0].date if tender.revisions else get_now()) > NORMALIZED_COMPLAINT_PERIOD_FROM and \
#             not (SANDBOX_MODE and tender.procurementMethodDetails):
#         if ceil:
#             return dt.astimezone(TZ).replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1)
#         return dt.astimezone(TZ).replace(hour=0, minute=0, second=0, microsecond=0)
#     return dt
# 
# Path: openprocurement/tender/openua/constants.py
# ENQUIRY_STAND_STILL_TIME = timedelta(days=3)
# 
# COMPLAINT_SUBMIT_TIME = timedelta(days=4)
# 
# TENDER_PERIOD = timedelta(days=15)
# 
# ENQUIRY_PERIOD_TIME = timedelta(days=10)
# 
# AUCTION_PERIOD_TIME = timedelta(days=2)
# 
# PERIOD_END_REQUIRED_FROM = datetime(2016, 7, 16, tzinfo=TZ)


from datetime import time, timedelta, datetime
from iso8601 import parse_date
from zope.interface import implementer
from pyramid.security import Allow
from schematics.exceptions import ValidationError
from schematics.transforms import whitelist, blacklist
from schematics.types import StringType, BooleanType
from schematics.types.compound import ModelType
from schematics.types.serializable import serializable
from openprocurement.api.utils import get_now
from openprocurement.api.models import (
    plain_role, listing_role,
    schematics_default_role, schematics_embedded_role, draft_role,
    Model, PeriodEndRequired as BasePeriodEndRequired,
    ListType, SifterListType, Period, IsoDateTimeType, Address
)
from openprocurement.api.constants import (
    TZ
)
from openprocurement.api.validation import (
    validate_cpv_group, validate_items_uniq
)
from openprocurement.tender.core.models import (
    view_role, create_role, edit_role,
    auction_view_role, auction_post_role, auction_patch_role,
    auction_role, chronograph_role, embedded_lot_role,
    chronograph_view_role, view_bid_role, Administrator_bid_role,
    get_tender, validate_lots_uniq, bids_validation_wrapper, Lot,
    ComplaintModelType, Award as BaseAward, Parameter as BaseParameter,
    Bid as BaseBid, Complaint as BaseComplaint,
    default_lot_role, LotValue as BaseLotValue, Item as BaseItem,
    Contract as BaseContract, Cancellation as BaseCancellation,
    validate_parameters_uniq, ITender,
    PeriodStartEndRequired,
    EnquiryPeriod
    # TenderAuctionPeriod
)
from openprocurement.tender.core.utils import (
    rounding_shouldStartAfter, calc_auction_end_time, calculate_business_date,
    has_unanswered_questions, has_unanswered_complaints
)
from openprocurement.tender.core.validation import (
    validate_LotValue_value,
)
from openprocurement.tender.belowthreshold.models import (
    Tender as BaseTender,
    enquiries_role,
    Administrator_role
)
from openprocurement.tender.openua.utils import (
    calculate_normalized_date
)
from openprocurement.tender.openua.constants import (
    ENQUIRY_STAND_STILL_TIME,
    COMPLAINT_SUBMIT_TIME,
    TENDER_PERIOD,
    ENQUIRY_PERIOD_TIME,
    AUCTION_PERIOD_TIME,
    PERIOD_END_REQUIRED_FROM,
)
class IAboveThresholdUATender(ITender):
     """ Marker interface for aboveThresholdUA tenders """


class TenderAuctionPeriod(Period):
    """The auction period."""

    @serializable(serialize_when_none=False)
    def shouldStartAfter(self):
        if self.endDate:
            return
        tender = self.__parent__
        if tender.lots or tender.status not in ['active.tendering', 'active.auction']:
            return
        if self.startDate and get_now() > calc_auction_end_time(tender.numberOfBids, self.startDate):
            start_after = calc_auction_end_time(tender.numberOfBids, self.startDate)
        else:
            decision_dates = [
                datetime.combine(complaint.dateDecision.date() + timedelta(days=3), time(0, tzinfo=complaint.dateDecision.tzinfo))
                for complaint in tender.complaints
                if complaint.dateDecision
            ]
            decision_dates.append(tender.tenderPeriod.endDate)
            start_after = max(decision_dates)
        return rounding_shouldStartAfter(start_after, tender).isoformat()

class PeriodEndRequired(BasePeriodEndRequired):
    #TODO different validator compared with belowthreshold
    def validate_startDate(self, data, value):
        tender = get_tender(data['__parent__'])

# Path: openprocurement/tender/openua/utils.py
# def calculate_normalized_date(dt, tender, ceil=False):
#     if (tender.revisions[0].date if tender.revisions else get_now()) > NORMALIZED_COMPLAINT_PERIOD_FROM and \
#             not (SANDBOX_MODE and tender.procurementMethodDetails):
#         if ceil:
#             return dt.astimezone(TZ).replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1)
#         return dt.astimezone(TZ).replace(hour=0, minute=0, second=0, microsecond=0)
#     return dt
# 
# Path: openprocurement/tender/openua/constants.py
# ENQUIRY_STAND_STILL_TIME = timedelta(days=3)
# 
# COMPLAINT_SUBMIT_TIME = timedelta(days=4)
# 
# TENDER_PERIOD = timedelta(days=15)
# 
# ENQUIRY_PERIOD_TIME = timedelta(days=10)
# 
# AUCTION_PERIOD_TIME = timedelta(days=2)
# 
# PERIOD_END_REQUIRED_FROM = datetime(2016, 7, 16, tzinfo=TZ)


# Path: openprocurement/tender/openua/models.py
from datetime import time, timedelta, datetime
from iso8601 import parse_date
from zope.interface import implementer
from pyramid.security import Allow
from schematics.exceptions import ValidationError
from schematics.transforms import whitelist, blacklist
from schematics.types import StringType, BooleanType
from schematics.types.compound import ModelType
from schematics.types.serializable import serializable
from openprocurement.api.utils import get_now
from openprocurement.api.models import (
    plain_role, listing_role,
    schematics_default_role, schematics_embedded_role, draft_role,
    Model, PeriodEndRequired as BasePeriodEndRequired,
    ListType, SifterListType, Period, IsoDateTimeType, Address
)
from openprocurement.api.constants import (
    TZ
)
from openprocurement.api.validation import (
    validate_cpv_group, validate_items_uniq
)
from openprocurement.tender.core.models import (
    view_role, create_role, edit_role,
    auction_view_role, auction_post_role, auction_patch_role,
    auction_role, chronograph_role, embedded_lot_role,
    chronograph_view_role, view_bid_role, Administrator_bid_role,
    get_tender, validate_lots_uniq, bids_validation_wrapper, Lot,
    ComplaintModelType, Award as BaseAward, Parameter as BaseParameter,
    Bid as BaseBid, Complaint as BaseComplaint,
    default_lot_role, LotValue as BaseLotValue, Item as BaseItem,
    Contract as BaseContract, Cancellation as BaseCancellation,
    validate_parameters_uniq, ITender,
    PeriodStartEndRequired,
    EnquiryPeriod
    # TenderAuctionPeriod
)
from openprocurement.tender.core.utils import (
    rounding_shouldStartAfter, calc_auction_end_time, calculate_business_date,
    has_unanswered_questions, has_unanswered_complaints
)
from openprocurement.tender.core.validation import (
    validate_LotValue_value,
)
from openprocurement.tender.belowthreshold.models import (
    Tender as BaseTender,
    enquiries_role,
    Administrator_role
)
from openprocurement.tender.openua.utils import (
    calculate_normalized_date
)
from openprocurement.tender.openua.constants import (
    ENQUIRY_STAND_STILL_TIME,
    COMPLAINT_SUBMIT_TIME,
    TENDER_PERIOD,
    ENQUIRY_PERIOD_TIME,
    AUCTION_PERIOD_TIME,
    PERIOD_END_REQUIRED_FROM,
)

class IAboveThresholdUATender(ITender):
     """ Marker interface for aboveThresholdUA tenders """


class TenderAuctionPeriod(Period):
    """The auction period."""

    @serializable(serialize_when_none=False)
    def shouldStartAfter(self):
        if self.endDate:
            return
        tender = self.__parent__
        if tender.lots or tender.status not in ['active.tendering', 'active.auction']:
            return
        if self.startDate and get_now() > calc_auction_end_time(tender.numberOfBids, self.startDate):
            start_after = calc_auction_end_time(tender.numberOfBids, self.startDate)
        else:
            decision_dates = [
                datetime.combine(complaint.dateDecision.date() + timedelta(days=3), time(0, tzinfo=complaint.dateDecision.tzinfo))
                for complaint in tender.complaints
                if complaint.dateDecision
            ]
            decision_dates.append(tender.tenderPeriod.endDate)
            start_after = max(decision_dates)
        return rounding_shouldStartAfter(start_after, tender).isoformat()

class PeriodEndRequired(BasePeriodEndRequired):
    #TODO different validator compared with belowthreshold
    def validate_startDate(self, data, value):
        tender = get_tender(data['__parent__'])

        if (tender.revisions[0].date if tender.revisions else get_now()) < PERIOD_END_REQUIRED_FROM: