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

type Captcha interface {
	Base
	// GetConfig required. Get the captcha plugin configuration.
	// The configuration is used to generate the captcha for frontend. Such as the token for third-party service.
	GetConfig() (configJsonStr string)
	// Create optional. If this plugin need to create captcha via backend, implement this method.
	// On other hand, if this plugin create captcha via third-party service, ignore this method.
	// Return captcha: The captcha image base64 string, code: The real captcha code.
	Create() (captcha, code string)
	// Verify required. Verify the user input captcha is correct or not
	// captcha: The captchaCode generated by Create method, if not implemented, it's empty.
	Verify(captchaCode, userInput string) (pass bool)
}

var (
	// CallCaptcha is a function that calls all registered parsers
	callCaptcha,
	registerCaptcha = MakePlugin[Captcha](false)
)

func CallCaptcha(fn func(fn Captcha) error) error {
	slugName := ""
	_ = callCaptcha(func(captcha Captcha) error {
		slugName = captcha.Info().SlugName
		return nil
	})
	if slugName == "" {
		return nil
	}
	return callCaptcha(func(captcha Captcha) error {
		if captcha.Info().SlugName == slugName {
			return fn(captcha)
		}
		return nil
	})
}

func CaptchaEnabled() (enabled bool) {
	_ = callCaptcha(func(fn Captcha) error {
		enabled = true
		return nil
	})
	return
}

func coordinatedCaptchaPlugins(slugName string) (enabledSlugNames []string) {
	isCaptcha := false
	_ = callCaptcha(func(captcha Captcha) error {
		name := captcha.Info().SlugName
		if slugName == name {
			isCaptcha = true
		} else {
			enabledSlugNames = append(enabledSlugNames, name)
		}
		return nil
	})
	if isCaptcha {
		return enabledSlugNames
	}
	return nil
}
