//
// 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 cloudstack

import (
	"encoding/json"
	"fmt"
	"log"
	"regexp"
	"strings"
	"time"

	"github.com/apache/cloudstack-go/v2/cloudstack"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceCloudstackInstance() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceCloudstackInstanceRead,
		Schema: map[string]*schema.Schema{
			"filter": dataSourceFiltersSchema(),

			//Computed values
			"instance_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"account": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"project": {
				Type:     schema.TypeString,
				Computed: true,
				Optional: true,
			},

			"display_name": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"state": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"host_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"zone_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"created": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"tags": tagsSchema(),

			"nic": {
				Type:     schema.TypeList,
				Computed: true,
				Optional: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"ip_address": {
							Type:     schema.TypeString,
							Computed: true,
							Optional: true,
						},
					},
				},
			},
		},
	}
}

func dataSourceCloudstackInstanceRead(d *schema.ResourceData, meta interface{}) error {
	log.Printf("Instance Data Source Read Started")

	cs := meta.(*cloudstack.CloudStackClient)
	p := cs.VirtualMachine.NewListVirtualMachinesParams()

	// If there is a project supplied, we retrieve and set the project id
	if err := setProjectid(p, cs, d); err != nil {
		return err
	}

	csInstances, err := cs.VirtualMachine.ListVirtualMachines(p)

	if err != nil {
		return fmt.Errorf("Failed to list instances: %s", err)
	}

	filters := d.Get("filter")
	nic := d.Get("nic").([]interface{})
	var instances []*cloudstack.VirtualMachine

	//the if-else block to check whether to filter the data source by an IP address
	// or by any other exported attributes
	if len(nic) != 0 {
		ip_address := nic[0].(map[string]interface{})["ip_address"]
		for _, i := range csInstances.VirtualMachines {
			if ip_address == i.Nic[0].Ipaddress {
				instances = append(instances, i)
			}
		}
	} else {
		for _, i := range csInstances.VirtualMachines {
			match, err := applyInstanceFilters(i, filters.(*schema.Set))
			if err != nil {
				return err
			}

			if match {
				instances = append(instances, i)
			}
		}
	}

	if len(instances) == 0 {
		return fmt.Errorf("No instance is matching with the specified regex")
	}
	//return the latest instance from the list of filtered instances according
	//to its creation date
	instance, err := latestInstance(instances)
	if err != nil {
		return err
	}
	log.Printf("[DEBUG] Selected instances: %s\n", instance.Displayname)

	return instanceDescriptionAttributes(d, instance)
}

func instanceDescriptionAttributes(d *schema.ResourceData, instance *cloudstack.VirtualMachine) error {
	d.SetId(instance.Id)
	d.Set("instance_id", instance.Id)
	d.Set("account", instance.Account)
	d.Set("project", instance.Project)
	d.Set("created", instance.Created)
	d.Set("display_name", instance.Displayname)
	d.Set("state", instance.State)
	d.Set("host_id", instance.Hostid)
	d.Set("zone_id", instance.Zoneid)
	d.Set("nic", []interface{}{map[string]string{"ip_address": instance.Nic[0].Ipaddress}})

	d.Set("tags", tagsToMap(instance.Tags))

	return nil
}

func latestInstance(instances []*cloudstack.VirtualMachine) (*cloudstack.VirtualMachine, error) {
	var latest time.Time
	var instance *cloudstack.VirtualMachine

	for _, i := range instances {
		created, err := time.Parse("2006-01-02T15:04:05-0700", i.Created)
		if err != nil {
			return nil, fmt.Errorf("Failed to parse creation date of an instance: %s", err)
		}

		if created.After(latest) {
			latest = created
			instance = i
		}
	}

	return instance, nil
}

func applyInstanceFilters(instance *cloudstack.VirtualMachine, filters *schema.Set) (bool, error) {
	var instanceJSON map[string]interface{}
	i, _ := json.Marshal(instance)
	err := json.Unmarshal(i, &instanceJSON)
	if err != nil {
		return false, err
	}

	for _, f := range filters.List() {
		m := f.(map[string]interface{})
		r, err := regexp.Compile(m["value"].(string))
		if err != nil {
			return false, fmt.Errorf("Invalid regex: %s", err)
		}
		updatedName := strings.ReplaceAll(m["name"].(string), "_", "")
		instanceField := instanceJSON[updatedName].(string)
		if !r.MatchString(instanceField) {
			return false, nil
		}

	}
	return true, nil
}
