# This is a derivative, modified, work from the verify-sigs project.
# Please refer to the LICENSE file in the distribution for more
# information. Original filename: asn1/pkcs7.py
#
# Parts of this file are licensed as follows:
#
# Copyright 2011 Google Inc. All Rights Reserved.
#
# 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.
#
# Partially derived from pyasn1 examples.

"""Subset of PKCS#7 message syntax."""

from pyasn1.type import namedtype
from pyasn1.type import tag
from pyasn1.type import univ
from . import x509


class Attribute(univ.Sequence):
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('type', x509.AttributeType()),
        namedtype.NamedType('values', univ.SetOf(
            componentType=x509.AttributeValue()
        ))
    )


class ContentType(univ.ObjectIdentifier):
    pass


class Version(univ.Integer):
    pass


class DigestAlgorithmIdentifier(x509.AlgorithmIdentifier):
    pass


class DigestAlgorithmIdentifiers(univ.SetOf):
    componentType = DigestAlgorithmIdentifier()


class Digest(univ.OctetString):
    pass


class DigestInfo(univ.Sequence):
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('digestAlgorithm', DigestAlgorithmIdentifier()),
        namedtype.NamedType('digest', Digest())
    )


class ContentInfo(univ.Sequence):
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('contentType', ContentType()),
        namedtype.OptionalNamedType('content', univ.Any().subtype(
            explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)
        ))
    )


class IssuerAndSerialNumber(univ.Sequence):
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('issuer', x509.Name()),
        namedtype.NamedType('serialNumber', x509.CertificateSerialNumber()))


class Attributes(univ.SetOf):
    componentType = Attribute()


class ExtendedCertificateInfo(univ.Sequence):
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('version', Version()),
        namedtype.NamedType('certificate', x509.Certificate()),
        namedtype.NamedType('attributes', Attributes())
    )


class SignatureAlgorithmIdentifier(x509.AlgorithmIdentifier):
    pass


class Signature(univ.BitString):
    pass


class ExtendedCertificate(univ.Sequence):
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('extendedCertificateInfo', ExtendedCertificateInfo()),
        namedtype.NamedType('signatureAlgorithm', SignatureAlgorithmIdentifier()),
        namedtype.NamedType('signature', Signature())
    )


class ExtendedCertificateOrCertificate(univ.Choice):
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('certificate', x509.Certificate()),
        namedtype.NamedType('extendedCertificate', ExtendedCertificate().subtype(
            implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)
        ))
    )


class ExtendedCertificatesAndCertificates(univ.SetOf):
    componentType = ExtendedCertificateOrCertificate()


class SerialNumber(univ.Integer):
    pass


class CertificateRevocationLists(univ.Any):
    pass


class DigestEncryptionAlgorithmIdentifier(x509.AlgorithmIdentifier):
    pass


class EncryptedDigest(univ.OctetString):
    pass


class SignerInfo(univ.Sequence):
    """As defined by PKCS#7."""
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('version', Version()),
        namedtype.NamedType('issuerAndSerialNumber', IssuerAndSerialNumber()),
        namedtype.NamedType('digestAlgorithm', DigestAlgorithmIdentifier()),
        namedtype.OptionalNamedType('authenticatedAttributes', Attributes().subtype(
            implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)
        )),
        namedtype.NamedType('digestEncryptionAlgorithm', DigestEncryptionAlgorithmIdentifier()),
        namedtype.NamedType('encryptedDigest', EncryptedDigest()),
        namedtype.OptionalNamedType('unauthenticatedAttributes', Attributes().subtype(
            implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)
        ))
    )


class SignerInfos(univ.SetOf):
    componentType = SignerInfo()


class SignedData(univ.Sequence):
    """As defined by PKCS#7."""

    componentType = namedtype.NamedTypes(
        namedtype.NamedType('version', Version()),
        namedtype.NamedType('digestAlgorithms', DigestAlgorithmIdentifiers()),
        namedtype.NamedType('contentInfo', ContentInfo()),
        namedtype.OptionalNamedType('certificates', ExtendedCertificatesAndCertificates().subtype(
                implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)
        )),
        namedtype.OptionalNamedType('crls', CertificateRevocationLists().subtype(
            implicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatConstructed, 1)
        )),
        namedtype.NamedType('signerInfos', SignerInfos())
    )


class Data(univ.OctetString):
    pass


class CountersignInfo(SignerInfo):
    pass


class SigningTime(x509.Time):
    pass
