# Path: roulier/api.py
# class ApiParcel(BaseApi):
#     """Define expected fields of carriers.
# 
#     This class should be overriden by each carrier.
#     """
# 
#     def _address(self):
#         return {
#             "company": {"type": "string", "default": ""},
#             "name": {"type": "string", "default": "", "required": True, "empty": False},
#             "street1": {"type": "string", "default": ""},
#             "street2": {"type": "string", "default": ""},
#             "country": {"type": "string", "default": ""},
#             # , 'description': 'ISO 3166-1 alpha-2 '},
#             "city": {"type": "string", "default": ""},
#             "zip": {"type": "string", "default": ""},
#             "phone": {"type": "string", "default": ""},
#             "email": {"type": "string", "default": ""},
#         }
# 
#     def _from_address(self):
#         address = self._address()
#         return address
# 
#     def _to_address(self):
#         address = self._address()
#         address["street1"].update({"required": True, "empty": False})
#         address["country"].update({"required": True, "empty": False})
#         address["city"].update({"required": True, "empty": False})
#         address["zip"].update({"required": True, "empty": False})
#         return address
# 
#     def _parcel(self):
#         return {
#             "weight": {
#                 "type": "float",
#                 "default": "",
#                 "required": True,
#                 "empty": False,
#             },
#             # reference of parcel in external app
#             # This ref should be attached to the label in roulier response so the
#             # external app is able to link a label file/tracking ref to the corresponding
#             # parcel.
#             "reference": {"type": "string"},
#         }
#         # 'description': 'Weight in kg',
# 
#     def _parcels(self):
#         return {
#             "type": "list",
#             "schema": {"schema": self._parcel(), "type": "dict"},
#         }
# 
#     def _service(self):
#         return {
#             "product": {"default": ""},
#             "agencyId": {"default": ""},
#             "customerId": {"default": ""},
#             "shippingId": {"default": ""},
#             # 'description': 'When the carrier has the package. Format: YYYY/MM/DD'
#             "shippingDate": {"type": "date", "required": True, "empty": False,},
#             # 'description': 'Additionnal info visible by the client. Example : order number'
#             "reference1": {"type": "string", "default": ""},
#             "reference2": {"type": "string", "default": ""},
#             "reference3": {"type": "string", "default": ""},
#             # 'description': 'Format of output (usually pdf or zpl)'
#             "labelFormat": {"default": ""},
#             # 'description': 'Additionnal instructions for delivery',
#             "instructions": {"default": ""},
#         }
# 
#     def _schemas(self):
#         return {
#             "service": self._service(),
#             "auth": self._auth(),
#             "parcels": self._parcels(),
#             "from_address": self._from_address(),
#             "to_address": self._to_address(),
#         }
# 
# Path: roulier/api.py
# class MyValidator(Validator):
#     """Custom validator."""
# 
#     def _normalize_coerce_zpl(self, value):
#         """Sanitze input for ZPL.
# 
#         Remove ZPL ctrl caraters
#         Remove accents
#         """
#         if not isinstance(value, str):
#             return value
# 
#         ctrl_cars = [
#             0xFE,  # Tilde ~
#             0x5E,  # Caret ^
#             0x1E,  # RS (^ substitution)
#             0x10,  # DLE (~ substitution)
#         ]
#         val = unidecode(value)
#         for ctrl in ctrl_cars:
#             val = val.replace("%c" % ctrl, "")
#         return val
# 
#     def _normalize_coerce_accents(self, value):
#         """Sanitize accents for some WS."""
#         if not isinstance(value, str):
#             return value
#         sanitized = (
#             (
#                 value
#                 # quick and dirty replacement
#                 # of common accentued chars in french
#                 # because some ws don't handle well utf8
#                 .replace("é", "e")
#                 .replace("è", "e")
#                 .replace("ë", "e")
#                 .replace("ê", "e")
#                 .replace("ô", "o")
#                 .replace("ï", "i")
#                 .replace("ö", "o")
#                 .replace("à", "a")
#                 .replace("â", "a")
#                 .replace("ç", "c")
#                 .replace("û", "u")
#                 .replace("ù", "u")
#                 .replace("É", "E")
#                 .replace("È", "E")
#                 .replace("Ë", "E")
#                 .replace("Ê", "E")
#                 .replace("Ô", "O")
#                 .replace("Ï", "I")
#                 .replace("Ö", "O")
#                 .replace("À", "A")
#                 .replace("Â", "A")
#                 .replace("Ç", "C")
#                 .replace("Û", "U")
#                 .replace("Ù", "U")
#                 .replace("œ", "oe")
#                 .replace("Œ", "OE")
#             )
#             .encode("ascii", "ignore")
#             .decode("ascii")
#         )  # cut remaining chars
#         return sanitized


from roulier.api import ApiParcel
from roulier.api import MyValidator
"""Implementation of Dpd Api."""


DPD_LABEL_FORMAT = (
    "PDF",
    "PDF_A6",
    "PNG",
    "ZPL",
)

DPD_ALLOWED_NOTIFICATIONS = (
    "No",
    "Predict",
    "AutomaticSMS",
    "AutomaticMail",
)
DPD_PRODUCTS = (
    "DPD_Classic",
    "DPD_Relais",
    "DPD_Predict",
    # 'DPD Retour en Relais',  # Not implemented yet
)



# Path: roulier/api.py
# class ApiParcel(BaseApi):
#     """Define expected fields of carriers.
# 
#     This class should be overriden by each carrier.
#     """
# 
#     def _address(self):
#         return {
#             "company": {"type": "string", "default": ""},
#             "name": {"type": "string", "default": "", "required": True, "empty": False},
#             "street1": {"type": "string", "default": ""},
#             "street2": {"type": "string", "default": ""},
#             "country": {"type": "string", "default": ""},
#             # , 'description': 'ISO 3166-1 alpha-2 '},
#             "city": {"type": "string", "default": ""},
#             "zip": {"type": "string", "default": ""},
#             "phone": {"type": "string", "default": ""},
#             "email": {"type": "string", "default": ""},
#         }
# 
#     def _from_address(self):
#         address = self._address()
#         return address
# 
#     def _to_address(self):
#         address = self._address()
#         address["street1"].update({"required": True, "empty": False})
#         address["country"].update({"required": True, "empty": False})
#         address["city"].update({"required": True, "empty": False})
#         address["zip"].update({"required": True, "empty": False})
#         return address
# 
#     def _parcel(self):
#         return {
#             "weight": {
#                 "type": "float",
#                 "default": "",
#                 "required": True,
#                 "empty": False,
#             },
#             # reference of parcel in external app
#             # This ref should be attached to the label in roulier response so the
#             # external app is able to link a label file/tracking ref to the corresponding
#             # parcel.
#             "reference": {"type": "string"},
#         }
#         # 'description': 'Weight in kg',
# 
#     def _parcels(self):
#         return {
#             "type": "list",
#             "schema": {"schema": self._parcel(), "type": "dict"},
#         }
# 
#     def _service(self):
#         return {
#             "product": {"default": ""},
#             "agencyId": {"default": ""},
#             "customerId": {"default": ""},
#             "shippingId": {"default": ""},
#             # 'description': 'When the carrier has the package. Format: YYYY/MM/DD'
#             "shippingDate": {"type": "date", "required": True, "empty": False,},
#             # 'description': 'Additionnal info visible by the client. Example : order number'
#             "reference1": {"type": "string", "default": ""},
#             "reference2": {"type": "string", "default": ""},
#             "reference3": {"type": "string", "default": ""},
#             # 'description': 'Format of output (usually pdf or zpl)'
#             "labelFormat": {"default": ""},
#             # 'description': 'Additionnal instructions for delivery',
#             "instructions": {"default": ""},
#         }
# 
#     def _schemas(self):
#         return {
#             "service": self._service(),
#             "auth": self._auth(),
#             "parcels": self._parcels(),
#             "from_address": self._from_address(),
#             "to_address": self._to_address(),
#         }
# 
# Path: roulier/api.py
# class MyValidator(Validator):
#     """Custom validator."""
# 
#     def _normalize_coerce_zpl(self, value):
#         """Sanitze input for ZPL.
# 
#         Remove ZPL ctrl caraters
#         Remove accents
#         """
#         if not isinstance(value, str):
#             return value
# 
#         ctrl_cars = [
#             0xFE,  # Tilde ~
#             0x5E,  # Caret ^
#             0x1E,  # RS (^ substitution)
#             0x10,  # DLE (~ substitution)
#         ]
#         val = unidecode(value)
#         for ctrl in ctrl_cars:
#             val = val.replace("%c" % ctrl, "")
#         return val
# 
#     def _normalize_coerce_accents(self, value):
#         """Sanitize accents for some WS."""
#         if not isinstance(value, str):
#             return value
#         sanitized = (
#             (
#                 value
#                 # quick and dirty replacement
#                 # of common accentued chars in french
#                 # because some ws don't handle well utf8
#                 .replace("é", "e")
#                 .replace("è", "e")
#                 .replace("ë", "e")
#                 .replace("ê", "e")
#                 .replace("ô", "o")
#                 .replace("ï", "i")
#                 .replace("ö", "o")
#                 .replace("à", "a")
#                 .replace("â", "a")
#                 .replace("ç", "c")
#                 .replace("û", "u")
#                 .replace("ù", "u")
#                 .replace("É", "E")
#                 .replace("È", "E")
#                 .replace("Ë", "E")
#                 .replace("Ê", "E")
#                 .replace("Ô", "O")
#                 .replace("Ï", "I")
#                 .replace("Ö", "O")
#                 .replace("À", "A")
#                 .replace("Â", "A")
#                 .replace("Ç", "C")
#                 .replace("Û", "U")
#                 .replace("Ù", "U")
#                 .replace("œ", "oe")
#                 .replace("Œ", "OE")
#             )
#             .encode("ascii", "ignore")
#             .decode("ascii")
#         )  # cut remaining chars
#         return sanitized


# Path: roulier/carriers/dpd_fr_soap/api.py
from roulier.api import ApiParcel
from roulier.api import MyValidator

"""Implementation of Dpd Api."""


DPD_LABEL_FORMAT = (
    "PDF",
    "PDF_A6",
    "PNG",
    "ZPL",
)

DPD_ALLOWED_NOTIFICATIONS = (
    "No",
    "Predict",
    "AutomaticSMS",
    "AutomaticMail",
)
DPD_PRODUCTS = (
    "DPD_Classic",
    "DPD_Relais",
    "DPD_Predict",
    # 'DPD Retour en Relais',  # Not implemented yet
)



class DpdValidator(MyValidator):