/*
Copyright 2016 The Kubernetes Authors.

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

package cloudstack

import (
	"context"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"

	"github.com/d2g/dhcp4"
	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/types"
	cloudprovider "k8s.io/cloud-provider"
	"k8s.io/klog"
)

var _ cloudprovider.Instances = (*metadata)(nil)
var _ cloudprovider.Zones = (*metadata)(nil)

type metadata struct {
	dhcpServer string
	zone       string
}

type metadataType string

const (
	metadataTypeHostname     metadataType = "local-hostname"
	metadataTypeExternalIP   metadataType = "public-ipv4"
	metadataTypeInternalIP   metadataType = "local-ipv4"
	metadataTypeInstanceID   metadataType = "instance-id"
	metadataTypeInstanceType metadataType = "service-offering"
	metadataTypeZone         metadataType = "availability-zone"
)

// NodeAddresses returns the addresses of the specified instance.
func (m *metadata) NodeAddresses(ctx context.Context, name types.NodeName) ([]v1.NodeAddress, error) {
	externalIP, err := m.get(metadataTypeExternalIP)
	if err != nil {
		return nil, fmt.Errorf("could not get external IP: %v", err)
	}

	internalIP, err := m.get(metadataTypeInternalIP)
	if err != nil {
		return nil, fmt.Errorf("could not get internal IP: %v", err)
	}

	addresses := []v1.NodeAddress{
		{Type: v1.NodeExternalIP, Address: externalIP},
		{Type: v1.NodeInternalIP, Address: internalIP},
	}

	hostname, err := m.get(metadataTypeHostname)
	if err != nil {
		return nil, fmt.Errorf("could not get hostname: %v", err)
	}
	if hostname != "" {
		addresses = append(addresses, v1.NodeAddress{Type: v1.NodeHostName, Address: hostname})
	}

	return addresses, nil
}

// NodeAddressesByProviderID returns the addresses of the specified instance.
func (m *metadata) NodeAddressesByProviderID(ctx context.Context, providerID string) ([]v1.NodeAddress, error) {
	return nil, errors.New("NodeAddressesByProviderID not implemented")
}

// InstanceID returns the cloud provider ID of the specified instance.
func (m *metadata) InstanceID(ctx context.Context, name types.NodeName) (string, error) {
	instanceID, err := m.get(metadataTypeInstanceID)
	if err != nil {
		return "", fmt.Errorf("could not get instance ID: %v", err)
	}

	zone, err := m.get(metadataTypeZone)
	if err != nil {
		return "", fmt.Errorf("could not get zone: %v", err)
	}

	return "/" + zone + "/" + instanceID, nil
}

// InstanceType returns the type of the specified instance.
func (m *metadata) InstanceType(ctx context.Context, name types.NodeName) (string, error) {
	instanceType, err := m.get(metadataTypeInstanceType)
	if err != nil {
		return "", fmt.Errorf("could not get instance type: %v", err)
	}

	return instanceType, nil
}

// InstanceTypeByProviderID returns the type of the specified instance.
func (m *metadata) InstanceTypeByProviderID(ctx context.Context, providerID string) (string, error) {
	return "", errors.New("InstanceTypeByProviderID not implemented")
}

// AddSSHKeyToAllInstances is currently not implemented.
func (m *metadata) AddSSHKeyToAllInstances(ctx context.Context, user string, keyData []byte) error {
	return cloudprovider.NotImplemented
}

// CurrentNodeName returns the name of the node we are currently running on.
func (m *metadata) CurrentNodeName(ctx context.Context, hostname string) (types.NodeName, error) {
	return types.NodeName(hostname), nil
}

// InstanceExistsByProviderID returns if the instance still exists.
func (m *metadata) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) {
	return false, errors.New("InstanceExistsByProviderID not implemented")
}

// InstanceShutdownByProviderID returns if the instance is shutdown.
func (m *metadata) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) {
	return false, cloudprovider.NotImplemented
}

// GetZone returns the Zone containing the region that the program is running in.
func (m *metadata) GetZone(ctx context.Context) (cloudprovider.Zone, error) {
	zone := cloudprovider.Zone{}

	if m.zone == "" {
		zoneName, err := m.get(metadataTypeZone)
		if err != nil {
			return zone, fmt.Errorf("could not get zone: %v", err)
		}

		m.zone = zoneName
	}

	klog.V(2).Infof("Current zone is %v", zone)
	zone.FailureDomain = m.zone
	zone.Region = m.zone

	return zone, nil
}

// GetZoneByProviderID returns the Zone, found by using the provider ID.
func (m *metadata) GetZoneByProviderID(ctx context.Context, providerID string) (cloudprovider.Zone, error) {
	return cloudprovider.Zone{}, errors.New("GetZoneByProviderID not implemented")
}

// GetZoneByNodeName returns the Zone, found by using the node name.
func (m *metadata) GetZoneByNodeName(ctx context.Context, nodeName types.NodeName) (cloudprovider.Zone, error) {
	return cloudprovider.Zone{}, errors.New("GetZoneByNodeName not implemented")
}

func (m *metadata) get(mdType metadataType) (string, error) {
	url := fmt.Sprintf("http://%s/latest/meta-data/%s", m.dhcpServer, mdType)

	resp, err := http.Get(url)
	if err != nil {
		return "", fmt.Errorf("error reading metadata: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("unexpected HTTP status: %d", resp.StatusCode)
	}

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("error reading response body: %d", resp.StatusCode)
	}

	return string(data), nil
}

func findDHCPServer() (string, error) {
	nics, err := net.Interfaces()
	if err != nil {
		return "", fmt.Errorf("could not get interfaces: %v", err)
	}

	for _, nic := range nics {
		if nic.Flags&net.FlagUp == 1 && nic.Flags&net.FlagLoopback == 0 && nic.Flags&net.FlagPointToPoint == 0 {
			addrs, err := nic.Addrs()
			if err != nil {
				return "", fmt.Errorf("error reading IP addresses from interface %v: %v", nic.Name, err)
			}

			if addrs != nil {
				client, err := newDHCPClient(&nic)
				if err != nil {
					return "", fmt.Errorf("error creating new DHCP client: %v", err)
				}

				discoverPacket, err := client.SendDiscoverPacket()
				if err != nil {
					return "", fmt.Errorf("error sending DHCP discover package: %v", err)
				}

				offerPacket, err := client.GetOffer(&discoverPacket)
				if err != nil {
					return "", fmt.Errorf("error receiving DHCP offer package: %v", err)
				}

				offerPacketOptions := offerPacket.ParseOptions()

				if ipaddr, ok := offerPacketOptions[dhcp4.OptionServerIdentifier]; ok {
					return net.IP(ipaddr).String(), nil
				}
			}
		}
	}

	return "", errors.New("no server found")
}
