from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc.textTools import safeEval
from fontTools.misc import sstruct
from . import DefaultTable
import base64

DSIG_HeaderFormat = """
	> # big endian
	ulVersion:      L
	usNumSigs:      H
	usFlag:         H
"""
# followed by an array of usNumSigs DSIG_Signature records
DSIG_SignatureFormat = """
	> # big endian
	ulFormat:       L
	ulLength:       L # length includes DSIG_SignatureBlock header
	ulOffset:       L
"""
# followed by an array of usNumSigs DSIG_SignatureBlock records,
# each followed immediately by the pkcs7 bytes
DSIG_SignatureBlockFormat = """
	> # big endian
	usReserved1:    H
	usReserved2:    H
	cbSignature:    l # length of following raw pkcs7 data
"""

#
# NOTE
# the DSIG table format allows for SignatureBlocks residing
# anywhere in the table and possibly in a different order as
# listed in the array after the first table header
#
# this implementation does not keep track of any gaps and/or data
# before or after the actual signature blocks while decompiling,
# and puts them in the same physical order as listed in the header
# on compilation with no padding whatsoever.
#

class table_D_S_I_G_(DefaultTable.DefaultTable):

	def decompile(self, data, ttFont):
		dummy, newData = sstruct.unpack2(DSIG_HeaderFormat, data, self)
		assert self.ulVersion == 1, "DSIG ulVersion must be 1"
		assert self.usFlag & ~1 == 0, "DSIG usFlag must be 0x1 or 0x0"
		self.signatureRecords = sigrecs = []
		for n in range(self.usNumSigs):
			sigrec, newData = sstruct.unpack2(DSIG_SignatureFormat, newData, SignatureRecord())
			assert sigrec.ulFormat == 1, "DSIG signature record #%d ulFormat must be 1" % n
			sigrecs.append(sigrec)
		for sigrec in sigrecs:
			dummy, newData = sstruct.unpack2(DSIG_SignatureBlockFormat, data[sigrec.ulOffset:], sigrec)
			assert sigrec.usReserved1 == 0, "DSIG signature record #%d usReserverd1 must be 0" % n
			assert sigrec.usReserved2 == 0, "DSIG signature record #%d usReserverd2 must be 0" % n
			sigrec.pkcs7 = newData[:sigrec.cbSignature]

	def compile(self, ttFont):
		packed = sstruct.pack(DSIG_HeaderFormat, self)
		headers = [packed]
		offset = len(packed) + self.usNumSigs * sstruct.calcsize(DSIG_SignatureFormat)
		data = []
		for sigrec in self.signatureRecords:
			# first pack signature block
			sigrec.cbSignature = len(sigrec.pkcs7)
			packed = sstruct.pack(DSIG_SignatureBlockFormat, sigrec) + sigrec.pkcs7
			data.append(packed)
			# update redundant length field
			sigrec.ulLength = len(packed)
			# update running table offset
			sigrec.ulOffset = offset
			headers.append(sstruct.pack(DSIG_SignatureFormat, sigrec))
			offset += sigrec.ulLength
		if offset % 2:
			# Pad to even bytes
			data.append(b'\0')
		return bytesjoin(headers+data)

	def toXML(self, xmlWriter, ttFont):
		xmlWriter.comment("note that the Digital Signature will be invalid after recompilation!")
		xmlWriter.newline()
		xmlWriter.simpletag("tableHeader", version=self.ulVersion, numSigs=self.usNumSigs, flag="0x%X" % self.usFlag)
		for sigrec in self.signatureRecords:
			xmlWriter.newline()
			sigrec.toXML(xmlWriter, ttFont)
		xmlWriter.newline()

	def fromXML(self, name, attrs, content, ttFont):
		if name == "tableHeader":
			self.signatureRecords = []
			self.ulVersion = safeEval(attrs["version"])
			self.usNumSigs = safeEval(attrs["numSigs"])
			self.usFlag = safeEval(attrs["flag"])
			return
		if name == "SignatureRecord":
			sigrec = SignatureRecord()
			sigrec.fromXML(name, attrs, content, ttFont)
			self.signatureRecords.append(sigrec)

pem_spam = lambda l, spam = {
	"-----BEGIN PKCS7-----": True, "-----END PKCS7-----": True, "": True
}: not spam.get(l.strip())

def b64encode(b):
	s = base64.b64encode(b)
	# Line-break at 76 chars.
	items = []
	while s:
		items.append(tostr(s[:76]))
		items.append('\n')
		s = s[76:]
	return strjoin(items)

class SignatureRecord(object):
	def __repr__(self):
		return "<%s: %s>" % (self.__class__.__name__, self.__dict__)

	def toXML(self, writer, ttFont):
		writer.begintag(self.__class__.__name__, format=self.ulFormat)
		writer.newline()
		writer.write_noindent("-----BEGIN PKCS7-----\n")
		writer.write_noindent(b64encode(self.pkcs7))
		writer.write_noindent("-----END PKCS7-----\n")
		writer.endtag(self.__class__.__name__)

	def fromXML(self, name, attrs, content, ttFont):
		self.ulFormat = safeEval(attrs["format"])
		self.usReserved1 = safeEval(attrs.get("reserved1", "0"))
		self.usReserved2 = safeEval(attrs.get("reserved2", "0"))
		self.pkcs7 = base64.b64decode(tobytes(strjoin(filter(pem_spam, content))))
