package main

import (
	"fmt"
	"strconv"
	"strings"
	"unicode"
)

func main() {
	// ExampleFirstClassFunctionArgument()
	// ExamplrUseNoNameFunction()
	// ExampleClosure()
	foo1()
}

func invert(r rune) rune {
	if unicode.IsLower(r) {
		return unicode.ToUpper(r)
	}
	return unicode.ToLower(r)
}

func ExampleFirstClassFunctionArgument() {
	src := "aBcDeFg"
	test := "AbCdEfG"

	// 1. Передача ранее определенной функции
	// Применяем функцию invert к каждому символу строки src
	//src = strings.Map(invert, src)
	//fmt.Printf("Инвертированная строка: %s. Результат: %v.\n", src, src == test)

	// 2. Передача анонимной функции
	src = strings.Map(func(r rune) rune {
		if unicode.IsLower(r) {
			return unicode.ToUpper(r)
		}
		return unicode.ToLower(r)
	}, src)
	fmt.Printf("Инвертированная строка: %s. Результат: %v.\n", src, src == test)
}

func ExamplrUseNoNameFunction() {
	// Присваимваем переменной fn анонимную функцию
	fn := func(a, b int) int { return a + b }

	// Выполняем анонимную функцию прямо на месте
	func(a, b int) {
		fmt.Println(a + b)
	}(12, 34) // Вызов анонимной функции

	// Выполняем функцию
	fmt.Println(fn(17, 15))
	fmt.Printf("%T", fn)

	x := func(fn func(i int) int, i int) func(int) int { return fn }(func(i int) int { return i + 1 }, 5)
	fmt.Printf("%T", x)
}

// Более сложный пример замыкания
func ExampleClosure() {
	fn := func() func(int) int {
		count := 0
		return func(i int) int {
			count++
			return count * i
		}
	}()

	for i := 1; i <= 5; i++ {
		fmt.Println(fn(i))
	}
}

func foo1() {
	fn := func(val uint) uint {
		s := strconv.Itoa(int(val))
		var newS string
		for i := 0; i < len(s); i++ {
			if s[i]%2 == 0 && s[i] != '0' {
				// fmt.Println(s[i])
				newS += string(s[i])
			}
		}
		fmt.Println(newS)

		if len(newS) == 0 {
			return 100
		} else {
			res, _ := strconv.Atoi(newS)
			return uint(res)
		}
	}

	fmt.Println(fn(0))
}
