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

import (
	"github.com/apache/apisix-ingress-controller/internal/types"
)

type ProviderType string

const (
	ProviderTypeStandalone ProviderType = "apisix-standalone"
	ProviderTypeAPISIX     ProviderType = "apisix"
)

// ListenerPortMatchMode selects when a Gateway listener port is turned into a
// server_port route var.
//
// It defaults to off because APISIX evaluates server_port against the port it
// actually accepted the connection on, which need not be the port the Gateway
// listener declares: a listener on 80 fronted by a Service that maps 80 to
// node_listen 9080 would emit `server_port == 80` and match nothing. Enabling
// it is only correct when the data plane listens on the declared ports.
type ListenerPortMatchMode string

const (
	ListenerPortMatchModeAuto     ListenerPortMatchMode = "auto"
	ListenerPortMatchModeExplicit ListenerPortMatchMode = "explicit"
	ListenerPortMatchModeOff      ListenerPortMatchMode = "off"
)

const (
	// IngressAPISIXLeader is the default election id for the controller
	// leader election.
	DefaultLeaderElectionID = "apisix-ingress-gateway-leader"

	// IngressClass is the default ingress class name, used for Ingress
	// object's IngressClassName field in Kubernetes clusters version v1.18.0
	// or higher, or the annotation "kubernetes.io/ingress.class" (deprecated).
	DefaultControllerName = "apisix.apache.org/apisix-ingress-controller"

	// DefaultLogLevel is the default log level for apisix-ingress-controller.
	DefaultLogLevel = "info"

	DefaultMetricsAddr = ":8080"
	DefaultProbeAddr   = ":8081"
	DefaultServerAddr  = ":9092"

	// Webhook configuration defaults
	DefaultWebhookTLSCert    = "tls.crt"
	DefaultWebhookTLSKey     = "tls.key"
	DefaultWebhookTLSCertDir = "/certs"
	DefaultWebhookPort       = 9443
)

// Config contains all config items which are necessary for
// apisix-ingress-controller's running.
type Config struct {
	LogLevel              string                `json:"log_level" yaml:"log_level"`
	ControllerName        string                `json:"controller_name" yaml:"controller_name"`
	LeaderElectionID      string                `json:"leader_election_id" yaml:"leader_election_id"`
	MetricsAddr           string                `json:"metrics_addr" yaml:"metrics_addr"`
	ServerAddr            string                `json:"server_addr" yaml:"server_addr"`
	EnableServer          bool                  `json:"enable_server" yaml:"enable_server"`
	EnableHTTP2           bool                  `json:"enable_http2" yaml:"enable_http2"`
	ProbeAddr             string                `json:"probe_addr" yaml:"probe_addr"`
	SecureMetrics         bool                  `json:"secure_metrics" yaml:"secure_metrics"`
	LeaderElection        *LeaderElection       `json:"leader_election" yaml:"leader_election"`
	ExecADCTimeout        types.TimeDuration    `json:"exec_adc_timeout" yaml:"exec_adc_timeout"`
	ProviderConfig        ProviderConfig        `json:"provider" yaml:"provider"`
	Webhook               *WebhookConfig        `json:"webhook" yaml:"webhook"`
	DisableGatewayAPI     bool                  `json:"disable_gateway_api" yaml:"disable_gateway_api"`
	ListenerPortMatchMode ListenerPortMatchMode `json:"listener_port_match_mode" yaml:"listener_port_match_mode"`
}

type GatewayConfig struct {
	Name         string              `json:"name" yaml:"name"`
	ControlPlane *ControlPlaneConfig `json:"control_plane" yaml:"control_plane"`
	Addresses    []string            `json:"addresses" yaml:"addresses"`
}

type ControlPlaneConfig struct {
	AdminKey  string   `json:"admin_key" yaml:"admin_key"`
	Endpoints []string `json:"endpoints" yaml:"endpoints"`
	TLSVerify *bool    `json:"tls_verify" yaml:"tls_verify"`
}

type LeaderElection struct {
	LeaseDuration types.TimeDuration `json:"lease_duration,omitempty" yaml:"lease_duration,omitempty"`
	RenewDeadline types.TimeDuration `json:"renew_deadline,omitempty" yaml:"renew_deadline,omitempty"`
	RetryPeriod   types.TimeDuration `json:"retry_period,omitempty" yaml:"retry_period,omitempty"`
	Disable       bool               `json:"disable,omitempty" yaml:"disable,omitempty"`
}

type ProviderConfig struct {
	Type          ProviderType       `json:"type" yaml:"type"`
	SyncPeriod    types.TimeDuration `json:"sync_period" yaml:"sync_period"`
	InitSyncDelay types.TimeDuration `json:"init_sync_delay" yaml:"init_sync_delay"`
}

type WebhookConfig struct {
	Enable      bool   `json:"enable" yaml:"enable"`
	TLSCertFile string `json:"tls_cert_file" yaml:"tls_cert_file"`
	TLSKeyFile  string `json:"tls_key_file" yaml:"tls_key_file"`
	TLSCertDir  string `json:"tls_cert_dir" yaml:"tls_cert_dir"`
	Port        int    `json:"port" yaml:"port"`
}
