// Licensed Materials - Property of IBM
// (c) Copyright IBM Corporation 2018, 2019. All Rights Reserved.
// Note to U.S. Government Users Restricted Rights:
// Use, duplication or disclosure restricted by GSA ADP Schedule
// Contract with IBM Corp.

package accesspolicy

import (
	//This package is required when using the IBM Cloud Clusters for its authentication
	_ "k8s.io/client-go/plugin/pkg/client/auth/oidc"

	"github.com/golang/glog"

	networkingv1 "k8s.io/api/networking/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	kubernetes "k8s.io/client-go/kubernetes"
)

// networkpoliciesmanager is an implementation for managing the lifecycle
// of NetworkPolicy resources in the cluster.
type networkpoliciesmanager struct {
	clientset *kubernetes.Clientset
}

var netpolmngr *networkpoliciesmanager

// getNetworkPoliciesManager will return the networkpoliciesmanager singleton
func getNetworkPoliciesManager(cset *kubernetes.Clientset) *networkpoliciesmanager {
	if netpolmngr == nil {
		netpolmngr = &networkpoliciesmanager{
			clientset: cset,
		}
	}

	return netpolmngr
}

// Create will create a new NetworkPolicy in the cluster
func (mgr *networkpoliciesmanager) create(policy *networkingv1.NetworkPolicy) error {
	name := policy.GetName()
	ns := policy.GetNamespace()

	_, err := mgr.clientset.NetworkingV1().NetworkPolicies(ns).Create(policy)
	if err != nil {
		glog.Error(err)
		return err
	}
	glog.Infof("NetworkPolicy '%s' created", name)

	return nil
}

// Get will get a NetworkPolicy named by the provided name. It the NetworkPolicy is not found,
// it will return nil for the policy. If failed find if it exists or get the policy the error will
// be returned.
func (mgr *networkpoliciesmanager) get(name string, ns string) (*networkingv1.NetworkPolicy, error) {
	options := metav1.GetOptions{}
	policy, err := mgr.clientset.NetworkingV1().NetworkPolicies(ns).Get(name, options)
	if err != nil {
		if apierrors.IsNotFound(err) {
			glog.Infof("NetworkPolicy '%s' not found", name)
			return nil, nil
		}
		return nil, err
	}

	glog.Infof("NetworkPolicy '%s' found", name)
	return policy, nil
}

// Delete will delete a NetworkPolicy
func (mgr *networkpoliciesmanager) delete(name string, ns string) error {
	err := mgr.clientset.NetworkingV1().NetworkPolicies(ns).Delete(name, nil)
	if err != nil {
		glog.Error(err)
		return err
	}
	glog.Infof("NetworkPolicy '%s' deleted", name)
	return nil
}

// Update will update an existing NetworkPolicy
func (mgr *networkpoliciesmanager) update(policy *networkingv1.NetworkPolicy) error {
	_, err := mgr.clientset.NetworkingV1().NetworkPolicies(policy.GetNamespace()).Update(policy)
	if err != nil {
		glog.Error(err)
		return err
	}
	glog.Infof("NetworkPolicy '%s' updated", policy.GetName())
	return nil
}
