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

import apisix "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"

// TranslateContext contains APISIX resources generated by the translator.
type TranslateContext struct {
	Routes       []*apisix.Route
	StreamRoutes []*apisix.StreamRoute
	Upstreams    []*apisix.Upstream
	upstreamMap  map[string]struct{}
	SSL          []*apisix.Ssl
}

func (tc *TranslateContext) addRoute(r *apisix.Route) {
	tc.Routes = append(tc.Routes, r)
}

func (tc *TranslateContext) addSSL(ssl *apisix.Ssl) {
	tc.SSL = append(tc.SSL, ssl)
}

func (tc *TranslateContext) addStreamRoute(sr *apisix.StreamRoute) {
	tc.StreamRoutes = append(tc.StreamRoutes, sr)
}

func (tc *TranslateContext) addUpstream(u *apisix.Upstream) {
	if _, ok := tc.upstreamMap[u.Name]; ok {
		return
	}
	tc.upstreamMap[u.Name] = struct{}{}
	tc.Upstreams = append(tc.Upstreams, u)
}

func (tc *TranslateContext) checkUpstreamExist(name string) (ok bool) {
	_, ok = tc.upstreamMap[name]
	return
}
