# generated by _messages_generator.py
# this file will be overwritten do not modify

import json
from typing import Union, Any, Dict
from dataclasses import dataclass

from .owl_common import Config, Curves, Point, ZKP


def get_curve(curve: Curves):
    
    from cryptography.hazmat.primitives.asymmetric import ec
    
    curve_map = {
        Curves.P256: ec.SECP256R1(),
        Curves.P384: ec.SECP384R1(),
        Curves.P521: ec.SECP521R1(),
    }
    return curve_map[curve]


def parse_num(x: Any) -> Union[int, None]:
    
    try:
        return int(f"0x{x}", 16)
    except (ValueError, TypeError):
        return None


def parse_point(x: Any, curve: Curves) -> Union[Point, None]:
    
    try:
        curve_obj = get_curve(curve)
        return Point.from_hex(x, curve_obj)
    except Exception:
        return None


def parse_zkp(x: Any) -> Union[ZKP, None]:
    
    try:
        h = parse_num(x.get('h')) if isinstance(x, dict) else None
        r = parse_num(x.get('r')) if isinstance(x, dict) else None
        if h is not None and r is not None:
            return ZKP(h=h, r=r)
    except Exception:
        pass
    return None


class DeserializationError(Exception):
    def __init__(self, message: str):
        super().__init__(message)
        self.name = "DeserializationError"


@dataclass
class RegistrationRequest:
    pi: int
    T: Point

    @classmethod
    def deserialize(
        cls,
        x: Any,
        cfg: Config,
    ) -> Union['RegistrationRequest', DeserializationError]:
        if isinstance(x, str):
            try:
                x = json.loads(x)
            except json.JSONDecodeError:
                return DeserializationError(
                    "Failed to deserialize RegistrationRequest: invalid JSON"
                )
        
        if x is not None:
            pi = parse_num(x.get('pi'))
            T = parse_point(x.get('T'), cfg.curve)
            
            if pi is not None and T is not None:
                return cls(pi=pi, T=T)
        
        return DeserializationError(
            "Failed to deserialize RegistrationRequest: invalid data"
        )
    
    def serialize(self) -> Dict[str, Any]:
        
        return {
            "pi": format(self.pi, 'x'),
            "T": self.T.to_hex(),
        }
    
    def to_json(self) -> str:
        
        return json.dumps(self.serialize())


@dataclass
class UserCredentials:
    X3: Point
    PI3: ZKP
    pi: int
    T: Point

    @classmethod
    def deserialize(
        cls,
        x: Any,
        cfg: Config,
    ) -> Union['UserCredentials', DeserializationError]:
        if isinstance(x, str):
            try:
                x = json.loads(x)
            except json.JSONDecodeError:
                return DeserializationError(
                    "Failed to deserialize UserCredentials: invalid JSON"
                )
        
        if x is not None:
            X3 = parse_point(x.get('X3'), cfg.curve)
            PI3 = parse_zkp(x.get('PI3'))
            pi = parse_num(x.get('pi'))
            T = parse_point(x.get('T'), cfg.curve)
            
            if X3 is not None and PI3 is not None and pi is not None and T is not None:
                return cls(X3=X3, PI3=PI3, pi=pi, T=T)
        
        return DeserializationError(
            "Failed to deserialize UserCredentials: invalid data"
        )
    
    def serialize(self) -> Dict[str, Any]:
        
        return {
            "X3": self.X3.to_hex(),
            "PI3": {"h": format(self.PI3.h, 'x'), "r": format(self.PI3.r, 'x')},
            "pi": format(self.pi, 'x'),
            "T": self.T.to_hex(),
        }
    
    def to_json(self) -> str:
        
        return json.dumps(self.serialize())


@dataclass
class AuthInitRequest:
    X1: Point
    X2: Point
    PI1: ZKP
    PI2: ZKP

    @classmethod
    def deserialize(
        cls,
        x: Any,
        cfg: Config,
    ) -> Union['AuthInitRequest', DeserializationError]:
        if isinstance(x, str):
            try:
                x = json.loads(x)
            except json.JSONDecodeError:
                return DeserializationError(
                    "Failed to deserialize AuthInitRequest: invalid JSON"
                )
        
        if x is not None:
            X1 = parse_point(x.get('X1'), cfg.curve)
            X2 = parse_point(x.get('X2'), cfg.curve)
            PI1 = parse_zkp(x.get('PI1'))
            PI2 = parse_zkp(x.get('PI2'))
            
            if X1 is not None and X2 is not None and PI1 is not None and PI2 is not None:
                return cls(X1=X1, X2=X2, PI1=PI1, PI2=PI2)
        
        return DeserializationError(
            "Failed to deserialize AuthInitRequest: invalid data"
        )
    
    def serialize(self) -> Dict[str, Any]:
        
        return {
            "X1": self.X1.to_hex(),
            "X2": self.X2.to_hex(),
            "PI1": {"h": format(self.PI1.h, 'x'), "r": format(self.PI1.r, 'x')},
            "PI2": {"h": format(self.PI2.h, 'x'), "r": format(self.PI2.r, 'x')},
        }
    
    def to_json(self) -> str:
        
        return json.dumps(self.serialize())


@dataclass
class AuthInitialValues:
    T: Point
    pi: int
    x4: int
    X1: Point
    X2: Point
    X3: Point
    X4: Point
    beta: Point
    PI1: ZKP
    PI2: ZKP
    PI3: ZKP
    PIBeta: ZKP

    @classmethod
    def deserialize(
        cls,
        x: Any,
        cfg: Config,
    ) -> Union['AuthInitialValues', DeserializationError]:
        if isinstance(x, str):
            try:
                x = json.loads(x)
            except json.JSONDecodeError:
                return DeserializationError(
                    "Failed to deserialize AuthInitialValues: invalid JSON"
                )
        
        if x is not None:
            T = parse_point(x.get('T'), cfg.curve)
            pi = parse_num(x.get('pi'))
            x4 = parse_num(x.get('x4'))
            X1 = parse_point(x.get('X1'), cfg.curve)
            X2 = parse_point(x.get('X2'), cfg.curve)
            X3 = parse_point(x.get('X3'), cfg.curve)
            X4 = parse_point(x.get('X4'), cfg.curve)
            beta = parse_point(x.get('beta'), cfg.curve)
            PI1 = parse_zkp(x.get('PI1'))
            PI2 = parse_zkp(x.get('PI2'))
            PI3 = parse_zkp(x.get('PI3'))
            PIBeta = parse_zkp(x.get('PIBeta'))
            
            if (T is not None and pi is not None and x4 is not None and
                X1 is not None and X2 is not None and X3 is not None and
                X4 is not None and beta is not None and PI1 is not None and
                PI2 is not None and PI3 is not None and PIBeta is not None):
                return cls(
                    T=T, pi=pi, x4=x4, X1=X1, X2=X2, X3=X3, X4=X4,
                    beta=beta, PI1=PI1, PI2=PI2, PI3=PI3, PIBeta=PIBeta
                )
        
        return DeserializationError(
            "Failed to deserialize AuthInitialValues: invalid data"
        )
    
    def serialize(self) -> Dict[str, Any]:
        
        return {
            "T": self.T.to_hex(),
            "pi": format(self.pi, 'x'),
            "x4": format(self.x4, 'x'),
            "X1": self.X1.to_hex(),
            "X2": self.X2.to_hex(),
            "X3": self.X3.to_hex(),
            "X4": self.X4.to_hex(),
            "beta": self.beta.to_hex(),
            "PI1": {"h": format(self.PI1.h, 'x'), "r": format(self.PI1.r, 'x')},
            "PI2": {"h": format(self.PI2.h, 'x'), "r": format(self.PI2.r, 'x')},
            "PI3": {"h": format(self.PI3.h, 'x'), "r": format(self.PI3.r, 'x')},
            "PIBeta": {"h": format(self.PIBeta.h, 'x'), "r": format(self.PIBeta.r, 'x')},
        }
    
    def to_json(self) -> str:
        
        return json.dumps(self.serialize())


@dataclass
class AuthInitResponse:
    X3: Point
    X4: Point
    PI3: ZKP
    PI4: ZKP
    beta: Point
    PIBeta: ZKP

    @classmethod
    def deserialize(
        cls,
        x: Any,
        cfg: Config,
    ) -> Union['AuthInitResponse', DeserializationError]:
        if isinstance(x, str):
            try:
                x = json.loads(x)
            except json.JSONDecodeError:
                return DeserializationError(
                    "Failed to deserialize AuthInitResponse: invalid JSON"
                )
        
        if x is not None:
            X3 = parse_point(x.get('X3'), cfg.curve)
            X4 = parse_point(x.get('X4'), cfg.curve)
            PI3 = parse_zkp(x.get('PI3'))
            PI4 = parse_zkp(x.get('PI4'))
            beta = parse_point(x.get('beta'), cfg.curve)
            PIBeta = parse_zkp(x.get('PIBeta'))
            
            if (X3 is not None and X4 is not None and PI3 is not None and
                PI4 is not None and beta is not None and PIBeta is not None):
                return cls(X3=X3, X4=X4, PI3=PI3, PI4=PI4, beta=beta, PIBeta=PIBeta)
        
        return DeserializationError(
            "Failed to deserialize AuthInitResponse: invalid data"
        )
    
    def serialize(self) -> Dict[str, Any]:
        
        return {
            "X3": self.X3.to_hex(),
            "X4": self.X4.to_hex(),
            "PI3": {"h": format(self.PI3.h, 'x'), "r": format(self.PI3.r, 'x')},
            "PI4": {"h": format(self.PI4.h, 'x'), "r": format(self.PI4.r, 'x')},
            "beta": self.beta.to_hex(),
            "PIBeta": {"h": format(self.PIBeta.h, 'x'), "r": format(self.PIBeta.r, 'x')},
        }
    
    def to_json(self) -> str:
        
        return json.dumps(self.serialize())


@dataclass
class AuthFinishRequest:
    alpha: Point
    PIAlpha: ZKP
    r: int

    @classmethod
    def deserialize(
        cls,
        x: Any,
        cfg: Config,
    ) -> Union['AuthFinishRequest', DeserializationError]:
        if isinstance(x, str):
            try:
                x = json.loads(x)
            except json.JSONDecodeError:
                return DeserializationError(
                    "Failed to deserialize AuthFinishRequest: invalid JSON"
                )
        
        if x is not None:
            alpha = parse_point(x.get('alpha'), cfg.curve)
            PIAlpha = parse_zkp(x.get('PIAlpha'))
            r = parse_num(x.get('r'))
            
            if alpha is not None and PIAlpha is not None and r is not None:
                return cls(alpha=alpha, PIAlpha=PIAlpha, r=r)
        
        return DeserializationError(
            "Failed to deserialize AuthFinishRequest: invalid data"
        )
    
    def serialize(self) -> Dict[str, Any]:
        
        return {
            "alpha": self.alpha.to_hex(),
            "PIAlpha": {"h": format(self.PIAlpha.h, 'x'), "r": format(self.PIAlpha.r, 'x')},
            "r": format(self.r, 'x'),
        }
    
    def to_json(self) -> str:
        
        return json.dumps(self.serialize())