/*
 * 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 getty

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
)
import (
	perrors "github.com/pkg/errors"
)

// TlsConfigBuilder  tls config builder interface
type TlsConfigBuilder interface {
	BuildTlsConfig() (*tls.Config, error)
}

// ServerTlsConfigBuilder impl TlsConfigBuilder for server
type ServerTlsConfigBuilder struct {
	ServerKeyCertChainPath        string
	ServerPrivateKeyPath          string
	ServerKeyPassword             string
	ServerTrustCertCollectionPath string
}

// BuildTlsConfig impl TlsConfigBuilder method
func (s *ServerTlsConfigBuilder) BuildTlsConfig() (*tls.Config, error) {
	var (
		err         error
		certPem     []byte
		certificate tls.Certificate
		certPool    *x509.CertPool
		config      *tls.Config
	)
	if certificate, err = tls.LoadX509KeyPair(s.ServerKeyCertChainPath, s.ServerPrivateKeyPath); err != nil {
		log.Error(fmt.Sprintf("tls.LoadX509KeyPair(certs{%s}, privateKey{%s}) = err:%+v",
			s.ServerKeyCertChainPath, s.ServerPrivateKeyPath, perrors.WithStack(err)))
		return nil, err
	}
	config = &tls.Config{
		InsecureSkipVerify: true, // do not verify peer certs
		ClientAuth:         tls.RequireAnyClientCert,
		Certificates:       []tls.Certificate{certificate},
	}

	if s.ServerTrustCertCollectionPath != "" {
		certPem, err = ioutil.ReadFile(s.ServerTrustCertCollectionPath)
		if err != nil {
			log.Error(fmt.Errorf("ioutil.ReadFile(certFile{%s}) = err:%+v", s.ServerTrustCertCollectionPath, perrors.WithStack(err)))
			return nil, err
		}
		certPool = x509.NewCertPool()
		if ok := certPool.AppendCertsFromPEM(certPem); !ok {
			log.Error("failed to parse root certificate file")
			return nil, err
		}
		config.ClientCAs = certPool
		config.ClientAuth = tls.RequireAnyClientCert
		config.InsecureSkipVerify = false
	}
	return config, nil
}

// ClientTlsConfigBuilder impl TlsConfigBuilder for client
type ClientTlsConfigBuilder struct {
	ClientKeyCertChainPath        string
	ClientPrivateKeyPath          string
	ClientKeyPassword             string
	ClientTrustCertCollectionPath string
}

// BuildTlsConfig impl TlsConfigBuilder method
func (c *ClientTlsConfigBuilder) BuildTlsConfig() (*tls.Config, error) {

	cert, err := tls.LoadX509KeyPair(c.ClientTrustCertCollectionPath, c.ClientPrivateKeyPath)
	if err != nil {
		log.Error(fmt.Sprintf("Unable to load X509 Key Pair %v", err))
		return nil, err
	}
	certBytes, err := ioutil.ReadFile(c.ClientTrustCertCollectionPath)
	if err != nil {
		log.Error(fmt.Sprintf("Unable to read pem file: %s", c.ClientTrustCertCollectionPath))
		return nil, err
	}
	clientCertPool := x509.NewCertPool()
	ok := clientCertPool.AppendCertsFromPEM(certBytes)
	if !ok {
		log.Error("failed to parse root certificate")
		return nil, err
	}
	return &tls.Config{
		RootCAs:            clientCertPool,
		Certificates:       []tls.Certificate{cert},
		InsecureSkipVerify: true,
	}, nil
}
