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

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

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

			//Computed values
			"name": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"dns1": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"internal_dns1": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"network_type": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func dataSourceCloudstackZoneRead(d *schema.ResourceData, meta interface{}) error {
	cs := meta.(*cloudstack.CloudStackClient)
	p := cs.Zone.NewListZonesParams()
	csZones, err := cs.Zone.ListZones(p)

	if err != nil {
		return fmt.Errorf("Failed to list zones: %s", err)
	}
	filters := d.Get("filter")
	var zone *cloudstack.Zone

	for _, z := range csZones.Zones {
		match, err := applyZoneFilters(z, filters.(*schema.Set))
		if err != nil {
			return err
		}
		if match {
			zone = z
		}
	}

	if zone == nil {
		return fmt.Errorf("No zone is matching with the specified regex")
	}
	log.Printf("[DEBUG] Selected zone: %s\n", zone.Name)

	return zoneDescriptionAttributes(d, zone)
}

func zoneDescriptionAttributes(d *schema.ResourceData, zone *cloudstack.Zone) error {
	d.SetId(zone.Name)
	d.Set("name", zone.Name)
	d.Set("dns1", zone.Dns1)
	d.Set("internal_dns1", zone.Internaldns1)
	d.Set("network_type", zone.Networktype)

	return nil
}

func applyZoneFilters(zone *cloudstack.Zone, filters *schema.Set) (bool, error) {
	var zoneJSON map[string]interface{}
	k, _ := json.Marshal(zone)
	err := json.Unmarshal(k, &zoneJSON)
	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), "_", "")
		zoneField := zoneJSON[updatedName].(string)
		if !r.MatchString(zoneField) {
			return false, nil
		}

	}
	return true, nil
}
