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

import (
	"encoding/base64"
	"net/url"
	"strconv"
	"strings"
	"sync"
)

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

import (
	"github.com/apache/dubbo-go/common"
	"github.com/apache/dubbo-go/common/constant"
)

// FileConditionRouter Use for parse config file of condition router
type FileConditionRouter struct {
	listenableRouter
	parseOnce sync.Once
	url       common.URL
}

// NewFileConditionRouter Create file condition router instance with content ( from config file)
func NewFileConditionRouter(content []byte) (*FileConditionRouter, error) {
	fileRouter := &FileConditionRouter{}
	rule, err := Parse(string(content))
	if err != nil {
		return nil, perrors.Errorf("yaml.Unmarshal() failed , error:%v", perrors.WithStack(err))
	}

	if !rule.Valid {
		return nil, perrors.Errorf("rule content is not verify for condition router , error:%v", perrors.WithStack(err))
	}

	fileRouter.generateConditions(rule)

	return fileRouter, nil
}

// URL Return URL in file condition router n
func (f *FileConditionRouter) URL() common.URL {
	f.parseOnce.Do(func() {
		routerRule := f.routerRule
		rule := parseCondition(routerRule.Conditions)
		f.url = *common.NewURLWithOptions(
			common.WithProtocol(constant.CONDITION_ROUTE_PROTOCOL),
			common.WithIp(constant.ANYHOST_VALUE),
			common.WithParams(url.Values{}),
			common.WithParamsValue(constant.RouterForce, strconv.FormatBool(routerRule.Force)),
			common.WithParamsValue(constant.RouterPriority, strconv.Itoa(routerRule.Priority)),
			common.WithParamsValue(constant.RULE_KEY, base64.URLEncoding.EncodeToString([]byte(rule))),
			common.WithParamsValue(constant.ROUTER_KEY, constant.CONDITION_ROUTE_PROTOCOL),
			common.WithParamsValue(constant.CATEGORY_KEY, constant.ROUTERS_CATEGORY))
	})
	return f.url
}

func parseCondition(conditions []string) string {
	var (
		when string
		then string
	)
	for _, condition := range conditions {
		condition = strings.Trim(condition, " ")
		if strings.Contains(condition, "=>") {
			array := strings.SplitN(condition, "=>", 2)
			consumer := strings.Trim(array[0], " ")
			provider := strings.Trim(array[1], " ")
			if len(consumer) != 0 {
				if len(when) != 0 {
					when = strings.Join([]string{when, consumer}, " & ")
				} else {
					when = consumer
				}
			}
			if len(provider) != 0 {
				if len(then) != 0 {
					then = strings.Join([]string{then, provider}, " & ")
				} else {
					then = provider
				}
			}

		}

	}

	return strings.Join([]string{when, then}, " => ")
}
