// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file contains examples to embed in the Go 1 release notes document.

package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"testing"
	"time"
	"unicode"
)

func main() {
	flag.Parse()
	stringAppend()
	mapDelete()
	mapIteration()
	multipleAssignment()
	structEquality()
	compositeLiterals()
	runeType()
	errorExample()
	timePackage()
	walkExample()
	osIsExist()
}

var timeout = flag.Duration("timeout", 30*time.Second, "how long to wait for completion")

func mapDelete() {
	m := map[string]int{"7": 7, "23": 23}
	k := "7"
	delete(m, k)
	if m["7"] != 0 || m["23"] != 23 {
		log.Fatal("mapDelete:", m)
	}
}

func stringAppend() {
	greeting := []byte{}
	greeting = append(greeting, []byte("hello ")...)
	greeting = append(greeting, "world"...)
	if string(greeting) != "hello world" {
		log.Fatal("stringAppend: ", string(greeting))
	}
}

func mapIteration() {
	m := map[string]int{"Sunday": 0, "Monday": 1}
	for name, value := range m {
		// This loop should not assume Sunday will be visited first.
		f(name, value)
	}
}

func f(string, int) {
}

func assert(t bool) {
	if !t {
		log.Panic("assertion fail")
	}
}

func multipleAssignment() {
	sa := []int{1, 2, 3}
	i := 0
	i, sa[i] = 1, 2 // sets i = 1, sa[0] = 2

	sb := []int{1, 2, 3}
	j := 0
	sb[j], j = 2, 1 // sets sb[0] = 2, j = 1

	sc := []int{1, 2, 3}
	sc[0], sc[0] = 1, 2 // sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)

	assert(i == 1 && sa[0] == 2)
	assert(j == 1 && sb[0] == 2)
	assert(sc[0] == 2)
}

func structEquality() {
	type Day struct {
		long  string
		short string
	}
	Christmas := Day{"Christmas", "XMas"}
	Thanksgiving := Day{"Thanksgiving", "Turkey"}
	holiday := map[Day]bool{
		Christmas:    true,
		Thanksgiving: true,
	}
	fmt.Printf("Christmas is a holiday: %t\n", holiday[Christmas])
}

func compositeLiterals() {
	type Date struct {
		month string
		day   int
	}
	// Struct values, fully qualified; always legal.
	holiday1 := []Date{
		Date{"Feb", 14},
		Date{"Nov", 11},
		Date{"Dec", 25},
	}
	// Struct values, type name elided; always legal.
	holiday2 := []Date{
		{"Feb", 14},
		{"Nov", 11},
		{"Dec", 25},
	}
	// Pointers, fully qualified, always legal.
	holiday3 := []*Date{
		&Date{"Feb", 14},
		&Date{"Nov", 11},
		&Date{"Dec", 25},
	}
	// Pointers, type name elided; legal in Go 1.
	holiday4 := []*Date{
		{"Feb", 14},
		{"Nov", 11},
		{"Dec", 25},
	}
	// STOP OMIT
	_, _, _, _ = holiday1, holiday2, holiday3, holiday4
}

func runeType() {
	// STARTRUNE OMIT
	delta := 'δ' // delta has type rune.
	var DELTA rune
	DELTA = unicode.ToUpper(delta)
	epsilon := unicode.ToLower(DELTA + 1)
	if epsilon != 'δ'+1 {
		log.Fatal("inconsistent casing for Greek")
	}
	// ENDRUNE OMIT
}

// START ERROR EXAMPLE OMIT
type SyntaxError struct {
	File    string
	Line    int
	Message string
}

func (se *SyntaxError) Error() string {
	return fmt.Sprintf("%s:%d: %s", se.File, se.Line, se.Message)
}

// END ERROR EXAMPLE OMIT

func errorExample() {
	var ErrSyntax = errors.New("syntax error")
	_ = ErrSyntax
	se := &SyntaxError{"file", 7, "error"}
	got := fmt.Sprint(se)
	const expect = "file:7: error"
	if got != expect {
		log.Fatalf("errorsPackage: expected %q got %q", expect, got)
	}
}

// sleepUntil sleeps until the specified time. It returns immediately if it's too late.
func sleepUntil(wakeup time.Time) {
	now := time.Now() // A Time.
	if !wakeup.After(now) {
		return
	}
	delta := wakeup.Sub(now) // A Duration.
	log.Printf("Sleeping for %.3fs", delta.Seconds())
	time.Sleep(delta)
}

func timePackage() {
	sleepUntil(time.Now().Add(123 * time.Millisecond))
}

func walkExample() {
	// STARTWALK OMIT
	markFn := func(path string, info os.FileInfo, err error) error {
		if path == "pictures" { // Will skip walking of directory pictures and its contents.
			return filepath.SkipDir
		}
		if err != nil {
			return err
		}
		log.Println(path)
		return nil
	}
	err := filepath.Walk(".", markFn)
	if err != nil {
		log.Fatal(err)
	}
	// ENDWALK OMIT
}

func initializationFunction(c chan int) {
	c <- 1
}

var PackageGlobal int

func init() {
	c := make(chan int)
	go initializationFunction(c)
	PackageGlobal = <-c
}

func BenchmarkSprintf(b *testing.B) {
	// Verify correctness before running benchmark.
	b.StopTimer()
	got := fmt.Sprintf("%x", 23)
	const expect = "17"
	if expect != got {
		b.Fatalf("expected %q; got %q", expect, got)
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		fmt.Sprintf("%x", 23)
	}
}

func osIsExist() {
	name := "go1.go"
	f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
	if os.IsExist(err) {
		log.Printf("%s already exists", name)
	}
	_ = f
}
