// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

package documents

import (
	"bytes"
	"fmt"

	"github.com/apache/incubator-milagro-dta/libs/crypto"
	"github.com/apache/incubator-milagro-dta/libs/cryptowallet"
	proto "github.com/golang/protobuf/proto"
	"github.com/pkg/errors"
)

var (
	errRecipientNotFound      = errors.New("Recipient not found")
	errFailedDecapsulation    = errors.New("Failed to decapsulate AES key")
	errFailedToGenerateAESKey = errors.New("Failed to generate Random aesKey")
)

//decapsulate - decapsulate the aes for Recipient ID in the list
func decapsulate(recipientCID string, recipients []*Recipient, sikeSK []byte) ([]byte, error) {
	for _, recipient := range recipients {
		if recipient.CID == recipientCID {
			return decapsulateWithRecipient(*recipient, sikeSK)
		}
	}
	return nil, errRecipientNotFound
}

func dup(orig []byte) []byte {
	dupSlice := make([]byte, len(orig))
	copy(dupSlice, orig)
	return dupSlice
}

func decapsulateWithRecipient(recipient Recipient, sikeSK []byte) ([]byte, error) {
	cipherText := recipient.CipherText
	encapsulatedKey := recipient.EncapsulatedKey
	encapIV := recipient.IV

	//Use duplicates of params, as DecapsulateDecrypt is destructive to inputs
	rc, recreatedAesKey := crypto.DecapsulateDecrypt(dup(cipherText), dup(encapIV), dup(sikeSK), dup(encapsulatedKey))

	if rc != 0 {
		return nil, errFailedDecapsulation
	}
	return recreatedAesKey, nil
}

func encapsulateKeyForRecipient(recipientsIDDocs map[string]*IDDoc, secret []byte) (recipientList []*Recipient, err error) {
	for id, idDocument := range recipientsIDDocs {
		r := &Recipient{}
		iv, err := cryptowallet.RandomBytes(16)
		if err != nil {
			return nil, errFailedToGenerateAESKey
		}
		r.CID = id
		r.IV = iv
		sikePK := idDocument.SikePublicKey

		//Use duplicates of params, as EncapsulateEncrypt is destructive to inputs
		rc, cipherText, encapsulatedKey := crypto.EncapsulateEncrypt(dup(secret), dup(iv), dup(sikePK))

		if rc != 0 {
			return nil, errFailedToGenerateAESKey
		}
		r.EncapsulatedKey = encapsulatedKey
		r.CipherText = cipherText
		recipientList = append(recipientList, r)
	}

	return recipientList, nil
}

func aesEncrypt(plainText []byte) (cipherText []byte, aesKey []byte, iv []byte, err error) {
	aesKey, err = cryptowallet.RandomBytes(32)
	if err != nil {
		return nil, nil, nil, errFailedToGenerateAESKey
	}
	iv, err = cryptowallet.RandomBytes(16)
	if err != nil {
		return nil, nil, nil, errFailedToGenerateAESKey
	}
	paddedText, err := pkcs7Pad(plainText, 32)
	if err != nil {
		return nil, nil, nil, errors.Wrap(err, "Failed to pad Document secret")
	}
	cipherText = crypto.AESCBCEncrypt(aesKey, iv, paddedText)
	return cipherText, aesKey, iv, nil
}

func aesDecrypt(cipherText []byte, iv []byte, aesKey []byte) (plainText []byte, err error) {
	pt := crypto.AESCBCDecrypt(aesKey, iv, cipherText)
	plainText, err = pkcs7Unpad(pt, 32)
	if err != nil {
		return nil, err
	}
	return plainText, nil
}

//Sign - generate a Signed envelope from the envelope
func sign(envelope Envelope, blsSK []byte, signerNodeID string) (SignedEnvelope, error) {
	envelopeBytes, err := proto.Marshal(&envelope)
	if err != nil {
		return SignedEnvelope{}, errors.Wrap(err, "Failed to serialize envelope in SignBLS")
	}
	rc, signature := crypto.BLSSign(envelopeBytes, blsSK)
	if rc != 0 {
		return SignedEnvelope{}, errors.Wrap(err, "Failed to sign envelope in in SignBLS")
	}
	signedEnvelope := SignedEnvelope{}
	signedEnvelope.SignerCID = signerNodeID
	signedEnvelope.Message = envelopeBytes
	signedEnvelope.Signature = signature
	return signedEnvelope, nil
}

//Verify verify the envelopes BLS signature
func Verify(signedEnvelope SignedEnvelope, blsPK []byte) error {
	message := signedEnvelope.Message
	signature := signedEnvelope.Signature

	if len(signature) == 0 {
		return errors.New("Invalid Signature")
	}

	rc := crypto.BLSVerify(message, blsPK, signature)
	if rc == 0 {
		return nil
	}
	return errors.New("Invalid signature")
}

// Appends padding.
func pkcs7Pad(data []byte, blocklen int) ([]byte, error) {
	if blocklen <= 0 {
		return nil, fmt.Errorf("invalid blocklen %d", blocklen)
	}
	padlen := 1
	for ((len(data) + padlen) % blocklen) != 0 {
		padlen = padlen + 1
	}
	pad := bytes.Repeat([]byte{byte(padlen)}, padlen)
	return append(data, pad...), nil
}

// Returns slice of the original data without padding.
func pkcs7Unpad(data []byte, blocklen int) ([]byte, error) {
	if blocklen <= 0 {
		return nil, fmt.Errorf("invalid blocklen %d", blocklen)
	}
	if len(data)%blocklen != 0 || len(data) == 0 {
		return nil, fmt.Errorf("invalid data len %d", len(data))
	}
	padlen := int(data[len(data)-1])
	if padlen > blocklen || padlen == 0 {
		return nil, fmt.Errorf("invalid padding")
	}
	// check padding
	pad := data[len(data)-padlen:]
	for i := 0; i < padlen; i++ {
		if pad[i] != byte(padlen) {
			return nil, fmt.Errorf("invalid padding")
		}
	}
	return data[:len(data)-padlen], nil
}
