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

import (
	"time"
)

import (
	perrors "github.com/pkg/errors"
)

import (
	"dubbo.apache.org/dubbo-go/v3/config"
)

const (
	TCPReadWriteTimeoutMinValue = time.Second * 1
)

type (
	// GettySessionParam is session configuration for getty
	GettySessionParam struct {
		CompressEncoding bool   `default:"false" yaml:"compress-encoding" json:"compress-encoding,omitempty"`
		TcpNoDelay       bool   `default:"true" yaml:"tcp-no-delay" json:"tcp-no-delay,omitempty"`
		TcpKeepAlive     bool   `default:"true" yaml:"tcp-keep-alive" json:"tcp-keep-alive,omitempty"`
		KeepAlivePeriod  string `default:"180s" yaml:"keep-alive-period" json:"keep-alive-period,omitempty"`
		keepAlivePeriod  time.Duration
		TcpRBufSize      int    `default:"262144" yaml:"tcp-r-buf-size" json:"tcp-r-buf-size,omitempty"`
		TcpWBufSize      int    `default:"65536" yaml:"tcp-w-buf-size" json:"tcp-w-buf-size,omitempty"`
		TcpReadTimeout   string `default:"1s" yaml:"tcp-read-timeout" json:"tcp-read-timeout,omitempty"`
		tcpReadTimeout   time.Duration
		TcpWriteTimeout  string `default:"5s" yaml:"tcp-write-timeout" json:"tcp-write-timeout,omitempty"`
		tcpWriteTimeout  time.Duration
		WaitTimeout      string `default:"7s" yaml:"wait-timeout" json:"wait-timeout,omitempty"`
		waitTimeout      time.Duration
		MaxMsgLen        int    `default:"1024" yaml:"max-msg-len" json:"max-msg-len,omitempty"`
		SessionName      string `default:"rpc" yaml:"session-name" json:"session-name,omitempty"`
	}

	// ServerConfig holds supported types by the multiconfig package
	ServerConfig struct {
		SSLEnabled bool

		// heartbeat
		HeartbeatPeriod string `default:"60s" yaml:"heartbeat-period" json:"heartbeat-period,omitempty"`
		heartbeatPeriod time.Duration

		// heartbeat timeout
		HeartbeatTimeout string `default:"5s" yaml:"heartbeat-timeout" json:"heartbeat-timeout,omitempty"`
		heartbeatTimeout time.Duration

		// session
		SessionTimeout string `default:"60s" yaml:"session-timeout" json:"session-timeout,omitempty"`
		sessionTimeout time.Duration
		SessionNumber  int `default:"1000" yaml:"session-number" json:"session-number,omitempty"`

		// gr pool
		GrPoolSize  int `default:"0" yaml:"gr-pool-size" json:"gr-pool-size,omitempty"`
		QueueLen    int `default:"0" yaml:"queue-len" json:"queue-len,omitempty"`
		QueueNumber int `default:"0" yaml:"queue-number" json:"queue-number,omitempty"`

		// session tcp parameters
		GettySessionParam GettySessionParam `required:"true" yaml:",inline" json:",inline"`
	}

	// ClientConfig holds supported types by the multi config package
	ClientConfig struct {
		ReconnectInterval int `default:"0" yaml:"reconnect-interval" json:"reconnect-interval,omitempty"`

		// session pool
		ConnectionNum int `default:"16" yaml:"connection-number" json:"connection-number,omitempty"`

		// heartbeat
		HeartbeatPeriod string `default:"60s" yaml:"heartbeat-period" json:"heartbeat-period,omitempty"`
		heartbeatPeriod time.Duration

		// heartbeat timeout
		HeartbeatTimeout string `default:"5s" yaml:"heartbeat-timeout" json:"heartbeat-timeout,omitempty"`
		heartbeatTimeout time.Duration

		// session
		SessionTimeout string `default:"60s" yaml:"session-timeout" json:"session-timeout,omitempty"`
		sessionTimeout time.Duration

		// gr pool
		GrPoolSize  int `default:"0" yaml:"gr-pool-size" json:"gr-pool-size,omitempty"`
		QueueLen    int `default:"0" yaml:"queue-len" json:"queue-len,omitempty"`
		QueueNumber int `default:"0" yaml:"queue-number" json:"queue-number,omitempty"`

		// session tcp parameters
		GettySessionParam GettySessionParam `required:"true" yaml:",inline" json:",inline"`
	}
)

// GetDefaultClientConfig gets client default configuration
func GetDefaultClientConfig() *ClientConfig {
	defaultClientConfig := &ClientConfig{
		ReconnectInterval: 0,
		ConnectionNum:     16,
		HeartbeatPeriod:   "30s",
		SessionTimeout:    "180s",
		GrPoolSize:        200,
		QueueLen:          64,
		QueueNumber:       10,
		GettySessionParam: GettySessionParam{
			CompressEncoding: false,
			TcpNoDelay:       true,
			TcpKeepAlive:     true,
			KeepAlivePeriod:  "180s",
			TcpRBufSize:      262144,
			TcpWBufSize:      65536,
			TcpReadTimeout:   "1s",
			TcpWriteTimeout:  "5s",
			WaitTimeout:      "1s",
			MaxMsgLen:        102400,
			SessionName:      "client",
		},
	}
	_ = defaultClientConfig.CheckValidity()
	return defaultClientConfig
}

// GetDefaultServerConfig gets server default configuration
func GetDefaultServerConfig() *ServerConfig {
	defaultServerConfig := &ServerConfig{
		SessionTimeout: "180s",
		SessionNumber:  700,
		GrPoolSize:     120,
		QueueNumber:    6,
		QueueLen:       64,
		GettySessionParam: GettySessionParam{
			CompressEncoding: false,
			TcpNoDelay:       true,
			TcpKeepAlive:     true,
			KeepAlivePeriod:  "180s",
			TcpRBufSize:      262144,
			TcpWBufSize:      65536,
			TcpReadTimeout:   "1s",
			TcpWriteTimeout:  "5s",
			WaitTimeout:      "1s",
			MaxMsgLen:        102400,
			SessionName:      "server",
		},
	}
	_ = defaultServerConfig.CheckValidity()
	return defaultServerConfig
}

// CheckValidity confirm getty session params
func (c *GettySessionParam) CheckValidity() error {
	var err error

	if c.keepAlivePeriod, err = time.ParseDuration(c.KeepAlivePeriod); err != nil {
		return perrors.WithMessagef(err, "time.ParseDuration(KeepAlivePeriod{%#v})", c.KeepAlivePeriod)
	}

	if c.tcpReadTimeout, err = parseTcpTimeoutDuration(c.TcpReadTimeout); err != nil {
		return perrors.WithMessagef(err, "time.ParseDuration(TcpReadTimeout{%#v})", c.TcpReadTimeout)
	}

	if c.tcpWriteTimeout, err = parseTcpTimeoutDuration(c.TcpWriteTimeout); err != nil {
		return perrors.WithMessagef(err, "time.ParseDuration(TcpWriteTimeout{%#v})", c.TcpWriteTimeout)
	}

	if c.waitTimeout, err = time.ParseDuration(c.WaitTimeout); err != nil {
		return perrors.WithMessagef(err, "time.ParseDuration(WaitTimeout{%#v})", c.WaitTimeout)
	}

	return nil
}

func parseTcpTimeoutDuration(timeStr string) (time.Duration, error) {
	result, err := time.ParseDuration(timeStr)
	if err != nil {
		return 0, err
	}
	if result < TCPReadWriteTimeoutMinValue {
		return TCPReadWriteTimeoutMinValue, nil
	}
	return result, nil
}

// CheckValidity confirm client params.
func (c *ClientConfig) CheckValidity() error {
	var err error

	c.ReconnectInterval = c.ReconnectInterval * 1e6

	if c.heartbeatPeriod, err = time.ParseDuration(c.HeartbeatPeriod); err != nil {
		return perrors.WithMessagef(err, "time.ParseDuration(HeartbeatPeroid{%#v})", c.HeartbeatPeriod)
	}

	if c.heartbeatPeriod >= time.Duration(config.MaxWheelTimeSpan) {
		return perrors.WithMessagef(err, "heartbeat-period %s should be less than %s",
			c.HeartbeatPeriod, time.Duration(config.MaxWheelTimeSpan))
	}

	if len(c.HeartbeatTimeout) == 0 {
		c.heartbeatTimeout = 60 * time.Second
	} else if c.heartbeatTimeout, err = time.ParseDuration(c.HeartbeatTimeout); err != nil {
		return perrors.WithMessagef(err, "time.ParseDuration(HeartbeatTimeout{%#v})", c.HeartbeatTimeout)
	}

	if c.sessionTimeout, err = time.ParseDuration(c.SessionTimeout); err != nil {
		return perrors.WithMessagef(err, "time.ParseDuration(SessionTimeout{%#v})", c.SessionTimeout)
	}

	return perrors.WithStack(c.GettySessionParam.CheckValidity())
}

// CheckValidity confirm server params
func (c *ServerConfig) CheckValidity() error {
	var err error

	if len(c.HeartbeatPeriod) == 0 {
		c.heartbeatPeriod = 60 * time.Second
	} else if c.heartbeatPeriod, err = time.ParseDuration(c.HeartbeatPeriod); err != nil {
		return perrors.WithMessagef(err, "time.ParseDuration(HeartbeatPeroid{%#v})", c.HeartbeatPeriod)
	}

	if c.heartbeatPeriod >= time.Duration(config.MaxWheelTimeSpan) {
		return perrors.WithMessagef(err, "heartbeat-period %s should be less than %s",
			c.HeartbeatPeriod, time.Duration(config.MaxWheelTimeSpan))
	}

	if len(c.HeartbeatTimeout) == 0 {
		c.heartbeatTimeout = 60 * time.Second
	} else if c.heartbeatTimeout, err = time.ParseDuration(c.HeartbeatTimeout); err != nil {
		return perrors.WithMessagef(err, "time.ParseDuration(HeartbeatTimeout{%#v})", c.HeartbeatTimeout)
	}

	if c.sessionTimeout, err = time.ParseDuration(c.SessionTimeout); err != nil {
		return perrors.WithMessagef(err, "time.ParseDuration(SessionTimeout{%#v})", c.SessionTimeout)
	}

	if c.sessionTimeout >= time.Duration(config.MaxWheelTimeSpan) {
		return perrors.WithMessagef(err, "session-timeout %s should be less than %s",
			c.SessionTimeout, time.Duration(config.MaxWheelTimeSpan))
	}

	return perrors.WithStack(c.GettySessionParam.CheckValidity())
}
