package main

import "fmt"

type file struct {
    name     string
	exist    bool
	openned  bool
	writable bool
}

func (f *file) open() {
	if !f.exist {
		panic("file does not exist!")
	}
	if f.openned {
		return
	}
	f.openned = true
	fmt.Println(f.name + ": openned")
}

func (f *file) write(data string) {
	if !f.openned {
		panic("can not write to closed file!")
	}
	if !f.writable {
		panic("can not write to file: permission denied!")
	}
	fmt.Println(f.name + ": writed: " + data)
}

func (f *file) close() {
	if f.openned {
		f.openned = false
		fmt.Println(f.name + ": closed")
	}
}

// --------------------------------

func (f *file) onOpenError() {
	if r := recover(); r != nil {
		fmt.Println(f.name + ":", r)
	}
}

func (f *file) onWriteError() {
	if r := recover(); r != nil {
		fmt.Println(f.name + ":", r)
	}
}

// --------------------------------

func makeTest(name string, exist bool, writable bool) func() {
	return func() {
		f := &file{name: name, exist: exist, openned: false, writable: writable}
		
		defer f.onOpenError()
		f.open()
	
		defer f.close()
		defer f.onWriteError()
		f.write("Hello!")
	}
}

var tests = []func(){
	makeTest("test1", false, false),
	makeTest("test2", false,  true),
	makeTest("test3", true,  false),
	makeTest("test4", true,   true),
}

func main() {
	for _, test := range tests {
		fmt.Println("--------------------------------")
		test()
	}
}
