package atscfg

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

import (
	"net"
	"sort"
	"strconv"
	"strings"

	"github.com/apache/trafficcontrol/lib/go-tc"
	"github.com/apache/trafficcontrol/lib/go-util"
)

const IPAllowConfigFileName = `ip_allow.config`
const ContentTypeIPAllowDotConfig = ContentTypeTextASCII
const LineCommentIPAllowDotConfig = LineCommentHash

const ParamPurgeAllowIP = "purge_allow_ip"
const ParamCoalesceMaskLenV4 = "coalesce_masklen_v4"
const ParamCoalesceNumberV4 = "coalesce_number_v4"
const ParamCoalesceMaskLenV6 = "coalesce_masklen_v6"
const ParamCoalesceNumberV6 = "coalesce_number_v6"

const DefaultCoalesceMaskLenV4 = 24
const DefaultCoalesceNumberV4 = 5
const DefaultCoalesceMaskLenV6 = 48
const DefaultCoalesceNumberV6 = 5

// IPAllowDotConfigOpts contains settings to configure generation options.
type IPAllowDotConfigOpts struct {
	// HdrComment is the header comment to include at the beginning of the file.
	// This should be the text desired, without comment syntax (like # or //). The file's comment syntax will be added.
	// To omit the header comment, pass the empty string.
	HdrComment string
}

// MakeIPAllowDotConfig creates the ip_allow.config ATS config file.
// The childServers is a list of servers which are children for this Mid-tier server. This should be empty for Edge servers.
// More specifically, it should be the list of edges whose cachegroup's parent_cachegroup or secondary_parent_cachegroup is the cachegroup of this Mid server.
func MakeIPAllowDotConfig(
	serverParams []tc.Parameter,
	server *Server,
	servers []Server,
	cacheGroups []tc.CacheGroupNullable,
	topologies []tc.Topology,
	opt *IPAllowDotConfigOpts,
) (Cfg, error) {
	if opt == nil {
		opt = &IPAllowDotConfigOpts{}
	}
	warnings := []string{}

	if server.Cachegroup == nil {
		return Cfg{}, makeErr(warnings, "this server missing Cachegroup")
	}
	if server.HostName == nil {
		return Cfg{}, makeErr(warnings, "this server missing HostName")
	}

	params := paramsToMultiMap(filterParams(serverParams, IPAllowConfigFileName, "", "", ""))

	ipAllowDat := []ipAllowData{}

	// default for coalesce_ipv4 = 24, 5 and for ipv6 48, 5; override with the parameters in the server profile.
	coalesceMaskLenV4 := DefaultCoalesceMaskLenV4
	coalesceNumberV4 := DefaultCoalesceNumberV4
	coalesceMaskLenV6 := DefaultCoalesceMaskLenV6
	coalesceNumberV6 := DefaultCoalesceNumberV6

	for name, vals := range params {
		for _, val := range vals {
			switch name {
			case ParamPurgeAllowIP:
				ipAllowDat = append(ipAllowDat, allowAll(val))
			case ParamCoalesceMaskLenV4:
				if vi, err := strconv.Atoi(val); err != nil {
					warnings = append(warnings, "got param '"+name+"' val '"+val+"' not a number, ignoring!")
				} else if coalesceMaskLenV4 != DefaultCoalesceMaskLenV4 {
					warnings = append(warnings, "got multiple param '"+name+"' - ignoring  val '"+val+"'!")
				} else {
					coalesceMaskLenV4 = vi
				}
			case ParamCoalesceNumberV4:
				if vi, err := strconv.Atoi(val); err != nil {
					warnings = append(warnings, "got param '"+name+"' val '"+val+"' not a number, ignoring!")
				} else if coalesceNumberV4 != DefaultCoalesceNumberV4 {
					warnings = append(warnings, "got multiple param '"+name+"' - ignoring  val '"+val+"'!")
				} else {
					coalesceNumberV4 = vi
				}
			case ParamCoalesceMaskLenV6:
				if vi, err := strconv.Atoi(val); err != nil {
					warnings = append(warnings, "got param '"+name+"' val '"+val+"' not a number, ignoring!")
				} else if coalesceMaskLenV6 != DefaultCoalesceMaskLenV6 {
					warnings = append(warnings, "got multiple param '"+name+"' - ignoring  val '"+val+"'!")
				} else {
					coalesceMaskLenV6 = vi
				}
			case ParamCoalesceNumberV6:
				if vi, err := strconv.Atoi(val); err != nil {
					warnings = append(warnings, "got param '"+name+"' val '"+val+"' not a number, ignoring!")
				} else if coalesceNumberV6 != DefaultCoalesceNumberV6 {
					warnings = append(warnings, "got multiple param '"+name+"' - ignoring  val '"+val+"'!")
				} else {
					coalesceNumberV6 = vi
				}
			}
		}
	}

	// for edges deny "PUSH|PURGE|DELETE", allow everything else to everyone.
	isMid := strings.HasPrefix(server.Type, tc.MidTypePrefix)
	if !isMid {
		ipAllowDat = append([]ipAllowData{allowAll(`127.0.0.1`)}, ipAllowDat...)
		ipAllowDat = append([]ipAllowData{allowAll(`::1`)}, ipAllowDat...)
		ipAllowDat = append(ipAllowDat, allowAllButPushPurgeDelete(`0.0.0.0-255.255.255.255`))
		ipAllowDat = append(ipAllowDat, allowAllButPushPurgeDelete(`::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff`))
	} else {

		ips := []*net.IPNet{}
		ip6s := []*net.IPNet{}

		cgMap := map[string]tc.CacheGroupNullable{}
		for _, cg := range cacheGroups {
			if cg.Name == nil {
				return Cfg{}, makeErr(warnings, "got cachegroup with nil name!")
			}
			cgMap[*cg.Name] = cg
		}

		if server.Cachegroup == nil {
			return Cfg{}, makeErr(warnings, "server had nil Cachegroup!")
		}

		serverCG, ok := cgMap[*server.Cachegroup]
		if !ok {
			return Cfg{}, makeErr(warnings, "server cachegroup not in cachegroups!")
		}

		childCGNames := getTopologyDirectChildren(tc.CacheGroupName(*server.Cachegroup), topologies)

		childCGs := map[string]tc.CacheGroupNullable{}
		for cgName, _ := range childCGNames {
			childCGs[string(cgName)] = cgMap[string(cgName)]
		}

		for cgName, cg := range cgMap {
			if (cg.ParentName != nil && *cg.ParentName == *serverCG.Name) || (cg.SecondaryParentName != nil && *cg.SecondaryParentName == *serverCG.Name) {
				childCGs[cgName] = cg
			}
		}

		// sort servers, to guarantee things like IP coalescing are deterministic
		sort.Sort(serversSortByName(servers))
		for _, childServer := range servers {
			if childServer.Cachegroup == nil {
				warnings = append(warnings, "Servers had server with nil Cachegroup, skipping!")
				continue
			} else if childServer.HostName == nil {
				warnings = append(warnings, "Servers had server with nil HostName, skipping!")
				continue
			}

			// We need to add IPs to the allow of
			// - all children of this server
			// - all monitors, if this server is a Mid
			//
			_, isChild := childCGs[*childServer.Cachegroup]
			if !isChild && !strings.HasPrefix(server.Type, tc.MidTypePrefix) && string(childServer.Type) != tc.MonitorTypeName {
				continue
			}

			for _, svInterface := range childServer.Interfaces {
				for _, svAddr := range svInterface.IPAddresses {
					if ip := net.ParseIP(svAddr.Address); ip != nil {
						// got an IP - convert it to a CIDR and add it to the list
						if ip4 := ip.To4(); ip4 != nil {
							ips = append(ips, util.IPToCIDR(ip4))
						} else {
							ip6s = append(ip6s, util.IPToCIDR(ip))
						}
					} else {
						// not an IP, try a CIDR
						if ip, cidr, err := net.ParseCIDR(svAddr.Address); err != nil {
							// not a CIDR or IP - error out
							warnings = append(warnings, "server '"+*server.HostName+"' IP '"+svAddr.Address+" is not an IP address or CIDR - skipping!")
						} else if ip == nil {
							// not a CIDR or IP - error out
							warnings = append(warnings, "server '"+*server.HostName+"' IP '"+svAddr.Address+" failed to parse as IP or CIDR - skipping!")
						} else {
							// got a valid CIDR - add it to the list
							if ip4 := ip.To4(); ip4 != nil {
								ips = append(ips, cidr)
							} else {
								ip6s = append(ip6s, cidr)
							}
						}
					}
				}
			}
		}

		cidrs := util.CoalesceCIDRs(ips, coalesceNumberV4, coalesceMaskLenV4)
		cidr6s := util.CoalesceCIDRs(ip6s, coalesceNumberV6, coalesceMaskLenV6)

		for _, cidr := range cidrs {
			ipAllowDat = append(ipAllowDat, allowAllButPushPurge(util.RangeStr(cidr)))
		}
		for _, cidr := range cidr6s {
			ipAllowDat = append(ipAllowDat, allowAllButPushPurge(util.RangeStr(cidr)))
		}

		// allow RFC 1918 server space - TODO JvD: parameterize
		ipAllowDat = append(ipAllowDat, allowAllButPushPurge(`10.0.0.0-10.255.255.255`))
		ipAllowDat = append(ipAllowDat, allowAllButPushPurge(`172.16.0.0-172.31.255.255`))
		ipAllowDat = append(ipAllowDat, allowAllButPushPurge(`192.168.0.0-192.168.255.255`))

		// order matters, so sort before adding the denys
		sort.Sort(ipAllowDatas(ipAllowDat))

		// start by allowing everything to localhost, including PURGE and PUSH
		ipAllowDat = append([]ipAllowData{allowAll(`127.0.0.1`)}, ipAllowDat...)
		ipAllowDat = append([]ipAllowData{allowAll(`::1`)}, ipAllowDat...)

		// end with a deny
		ipAllowDat = append(ipAllowDat, denyAll(`0.0.0.0-255.255.255.255`))
		ipAllowDat = append(ipAllowDat, denyAll(`::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff`))
	}

	text := makeHdrComment(opt.HdrComment)
	for _, al := range ipAllowDat {
		text += `src_ip=` + al.Src + ` action=` + al.Action + ` method=` + al.Method + "\n"
	}

	return Cfg{
		Text:        text,
		ContentType: ContentTypeHostingDotConfig,
		LineComment: LineCommentHostingDotConfig,
		Warnings:    warnings,
	}, nil
}

type ipAllowData struct {
	Src    string
	Action string
	Method string
}

type ipAllowDatas []ipAllowData

func (is ipAllowDatas) Len() int      { return len(is) }
func (is ipAllowDatas) Swap(i, j int) { is[i], is[j] = is[j], is[i] }
func (is ipAllowDatas) Less(i, j int) bool {
	if is[i].Src != is[j].Src {
		return is[i].Src < is[j].Src
	}
	if is[i].Action != is[j].Action {
		return is[i].Action < is[j].Action
	}
	return is[i].Method < is[j].Method
}

type ipAllowServer struct {
	IPAddress  string
	IP6Address string
}

type serversSortByName []Server

func (ss serversSortByName) Len() int      { return len(ss) }
func (ss serversSortByName) Swap(i, j int) { ss[i], ss[j] = ss[j], ss[i] }
func (ss serversSortByName) Less(i, j int) bool {
	if ss[j].HostName == nil {
		return false
	} else if ss[i].HostName == nil {
		return true
	}
	return *ss[i].HostName < *ss[j].HostName
}

const ActionAllow = "ip_allow"
const ActionDeny = "ip_deny"
const MethodAll = "ALL"
const MethodPush = "PUSH"
const MethodPurge = "PURGE"
const MethodDelete = "DELETE"
const MethodSeparator = `|`

// allowAllButPushPurge is a helper func to build a ipAllowData for the given range string immediately allowing all Methods except Push and Purge.
func allowAllButPushPurge(rangeStr string) ipAllowData {
	// Note denying methods implicitly and immediately allows all other methods!
	// So Deny PUSH|PURGE will make all other methods
	// immediately allowed, regardless of any later deny rules!
	methodPushPurge := strings.Join([]string{MethodPush, MethodPurge}, MethodSeparator)
	return ipAllowData{
		Src:    rangeStr,
		Action: ActionDeny,
		Method: methodPushPurge,
	}
}

// allowAllButPushPurgeDelete is a helper func to build a ipAllowData for the given range string immediately allowing all Methods except PUSH, PURGE, and DELETE.
func allowAllButPushPurgeDelete(rangeStr string) ipAllowData {
	// Note denying methods implicitly and immediately allows all other methods!
	// So Deny PUSH|PURGE will make all other methods
	// immediately allowed, regardless of any later deny rules!
	methodPushPurgeDelete := strings.Join([]string{MethodPush, MethodPurge, MethodDelete}, MethodSeparator)
	return ipAllowData{
		Src:    rangeStr,
		Action: ActionDeny,
		Method: methodPushPurgeDelete,
	}
}

// allowAll is a helper func to build a ipAllowData for the given range string immediately allowing all Methods, including Push and Purge.
func allowAll(rangeStr string) ipAllowData {
	return ipAllowData{
		Src:    rangeStr,
		Action: ActionAllow,
		Method: MethodAll,
	}
}

// denyAll is a helper func to build a ipAllowData for the given range string immediately denying all Methods.
func denyAll(rangeStr string) ipAllowData {
	return ipAllowData{
		Src:    rangeStr,
		Action: ActionDeny,
		Method: MethodAll,
	}
}
