func main() {

	var test = flag.Bool("test", false, "go in test use?")
	flag.Parse()

	d.DELETE_DB = *test
	m.DEBUG = *test
	m.TEST = *test
	conf := configuration.ReadConfig()

	db := d.NewMainDb(conf.Main.Database.ConnString, conf.Main.Database.Name)
	log.Printf("Is delete DB? [%+v] Is debug? [%v]", d.DELETE_DB, m.DEBUG)
	if d.DELETE_DB {
		log.Println("!!!!!!!!!!start at test mode!!!!!!!!!!!!!")
		conf.Main.Database.Name = conf.Main.Database.Name + "_test"
		db.Session.DB(conf.Main.Database.Name).DropDatabase()
		db = d.NewMainDb(conf.Main.Database.ConnString, conf.Main.Database.Name)
	}

	InsertTestUser(db, "test", "test")
	InsertTestUser(db, "test1", "test1")
	InsertTestUser(db, "test2", "test2")
	result := make(chan string, 1000)
	i.StartBot(db, result)
}
func formTestMartini() *martini.Martini {
	config := configuration.ReadTestConfigInRecursive()
	mainDb := db.NewMainDb(config.Main.Database.ConnString, config.Main.Database.Name)
	m := web.NewSessionAuthorisationHandler(mainDb)
	m.Use(render.Renderer(render.Options{
		Directory:  "templates/auth",
		Extensions: []string{".tmpl", ".html"},
		Charset:    "UTF-8",
	}))
	router := martini.NewRouter()

	router.Get("/", func(r render.Render) {
		r.HTML(200, "login", nil)
	})
	router.Group("/test", func(r martini.Router) {
		r.Get("/:id", func(ren render.Render, prms martini.Params) {
			id := prms["id"]
			ren.JSON(200, map[string]interface{}{"id": id})
		})
		r.Get("/new", func(ren render.Render) {
			ren.JSON(200, nil)
		})
		r.Get("/update/:id", func(ren render.Render, prms martini.Params) {
			id := prms["id"]
			ren.JSON(200, map[string]interface{}{"id": id})
		})
		r.Get("/delete/:id", func(ren render.Render, prms martini.Params) {
			id := prms["id"]
			ren.JSON(200, map[string]interface{}{"id": id})
		})
	})
	m.Action(router.Handle)
	return m
}
func main() {
	conf := c.ReadConfig()
	handler := db.NewMainDb(conf.Main.Database.ConnString, conf.Main.Database.Name)
	s.StartAfter(func() (string, bool) {
		return "", handler.Check()
	}, func() {
		log.Printf("connection established....")
	})

	log.Println("Starting migration 1...")
	users_collection := handler.Session.DB(conf.Main.Database.Name).C("users")
	users_collection.UpdateAll(bson.M{}, bson.M{"$set": bson.M{"states": bson.M{}}})

}
func TestWum(t *testing.T) {
	conf := configuration.ReadTestConfigInRecursive()
	db := db.NewMainDb(conf.Main.Database.ConnString, conf.Main.Database.Name)
	wum := NewWatchManager(db, "test")
	go wum.WatchUnreadMessages()

	for i, el := range []string{"one", "two", "three"} {
		wum.AddConfiguration(el, "test", "key", 2)
		if len(wum.Configs) != i+1 {
			t.Error("bad configs count")
		}
		time.Sleep(10)
	}
}
func TestBot(t *testing.T) {
	conf := c.ReadConfig()
	var test = flag.Bool("test", false, "go in test use?")
	flag.Parse()
	DEBUG = true
	d.DELETE_DB = *test
	log.Printf("Is test? [%+v] Will delete db? [%+v]", *test, d.DELETE_DB)
	if d.DELETE_DB {
		log.Println("!start at test mode!")
		conf.Main.Database.Name = conf.Main.Database.Name + "_test"
	}
	db := d.NewMainDb(conf.Main.Database.ConnString, conf.Main.Database.Name)

	for _, shop_conf := range conf.Shops {
		bot_context := sh.FormShopCommands(db, &shop_conf)
		shop_controller := FormBotController(bot_context)
		shop_route := fmt.Sprintf("/shop/%v", shop_conf.Name)
		log.Println("will wait requests at :", shop_route)
		http.HandleFunc(shop_route, shop_controller)
	}

	server_address := fmt.Sprintf(":%v", conf.Main.Port)
	s.StartAfter(func() (string, bool) {
		return "", db.Check()
	}, func() {
		log.Printf("\nStart listen and serving at: %v\n", server_address)
		server := &http.Server{
			Addr: server_address,
		}

		log.Fatal(server.ListenAndServe())
	})

	log.Printf("will send requests....")

	addr := fmt.Sprintf("http://localhost:%v/shop/test_shop", conf.Main.Port)
	send_post("shop_balance_ok.json", addr)
	send_post("shop_balance_error.json", addr)
	send_post("request_commands.json", addr)
	t.Log("test ended...")
}
func main() {
	conf := c.ReadConfig()
	handler := db.NewMainDb(conf.Main.Database.ConnString, conf.Main.Database.Name)
	s.StartAfter(func() (string, bool) {
		return "", handler.Check()
	}, func() {
		log.Printf("connection established....")
	})

	log.Println("Starting migration 0...")
	orders_collection := handler.Session.DB(conf.Main.Database.Name).C("orders")
	err := orders_collection.DropIndex("order_id")
	if err != nil {
		panic(err)
	}
	err = orders_collection.EnsureIndex(mgo.Index{
		Key:        []string{"order_id"},
		Background: true,
		Unique:     false,
		DropDups:   true,
	})
	log.Printf("Index for order_id field is recreated...%v", err)
}
func main() {
	config := configuration.ReadTestConfigInRecursive()
	mainDb := db.NewMainDb(config.Main.Database.ConnString, config.Main.Database.Name)
	web.TestRun(mainDb)
}
func main() {
	msngr.TEST = true
	msngr.DEBUG = true

	cnf := configuration.ReadConfig()
	cnf.SetLogFile("test.log")
	error_chan := make(chan structs.MessageError, 10)
	ha := tstu.HandleAddress("/notify", ":9876", error_chan)
	for {
		res := <-ha
		log.Printf("HANDLE ADDR %v", res)
		if res == "listen" {
			break
		}
	}

	main_db := db.NewMainDb(cnf.Main.Database.ConnString, cnf.Main.Database.Name)
	//start_bot_result := make(chan string, 100)
	//go i.StartBot(main_db, start_bot_result)
	//for {
	//	res := <-start_bot_result
	//	log.Printf("BOT ENGINE: %v", res)
	//	if res == "listen" {
	//		break
	//	}
	//
	//}
	merror := structs.MessageError{
		Code:      500,
		Type:      "wait",
		Condition: "resource-constraint",
	}
	error_chan <- merror
	ntfr := ntf.NewNotifier(cnf.Main.CallbackAddr, "test_key", main_db)
	out_pkg, err := ntfr.NotifyText("TEST", "TEST MESSAGE")
	log.Printf("> NTF OUT IS: %v,\n err: %v", out_pkg, err)
	result, err := tstu.POST(address, &structs.InPkg{
		Message: &structs.InMessage{
			ID:    out_pkg.Message.ID,
			Error: &merror,
			Body:  &out_pkg.Message.Body,
		},
		From:     out_pkg.To,
		UserData: &structs.InUserData{Name: "TEST"},
	})
	log.Printf("ANSWER must be empty %v, %v", result, err)
	mess := "hui"
	merror.Code = 404
	result, err = tstu.POST(address, &structs.InPkg{
		Message: &structs.InMessage{
			ID:    mess,
			Error: &merror,
			Body:  &mess,
		},
		From:     out_pkg.To,
		UserData: &structs.InUserData{Name: "TEST"},
	})
	log.Printf("ANSWER must be empty %v %v", result, err)

	//result_outs := []*structs.OutPkg{}
	//for _, i := range []int{1, 2, 3, 4, 5, 6, 7} {
	//	out, err := ntfr.NotifyText("TEST", fmt.Sprintf("NOTIFY TST MESSSAGE %v", i))
	//	if out != nil {
	//		result_outs = append(result_outs, out)
	//		mw, err := main_db.Messages.GetMessageByMessageId(out.Message.ID)
	//		log.Printf("ASSERT sended status notify message? %v Err? %v", mw.MessageStatus, err)
	//	}else {
	//		log.Printf("WARN sended status notify message? %+v Err? %v", out, err)
	//	}
	//
	//}
	//
	//for _, out := range result_outs {
	//	if out.Message != nil {
	//		in := &structs.InPkg{
	//			Message:&structs.InMessage{
	//				Body:&out.Message.Body,
	//				Type:"error",
	//				Error:&out.Message.Error,
	//			},
	//			From:out.To,
	//			UserData:&structs.InUserData{Name:"TEST"},
	//		}
	//		log.Printf("TST_ERR_MESS send: \n\t%+v", in)
	//		out_echo, err := tstu.POST(address, in)
	//		log.Printf("ASSERT out_echo nil? %v and err:%v", out_echo == nil, err)
	//	}
	//	mw, err := main_db.Messages.GetMessageByMessageId(out.Message.ID)
	//	log.Printf("ASSERT err? %v we have this message? %v They have similar errors?: %v\n...message:\n%+v", err == nil, mw != nil, mw.MessageStatus == "error", mw.MessageCondition == out.Message.Error.Condition, )
	//
	//}
}
func EnsureStatistic(toPath string) error {
	var file *xlsx.File
	var sheet *xlsx.Sheet
	var row *xlsx.Row
	var cell *xlsx.Cell
	var err error

	file = xlsx.NewFile()
	type Source struct {
		Name string `bson:"_id"`
	}
	sources := []Source{}
	dbsWithOrders := getDbsWithOrders()
	log.Printf("Databases with orders is: %+v", dbsWithOrders)

	for _, dbName := range dbsWithOrders {
		db := d.NewMainDb(config.Main.Database.ConnString, dbName)
		sheet, err = file.AddSheet(dbName)
		if err != nil {
			log.Printf("Error at edding sheet to file")
			continue
		}
		db.Orders.Collection.Pipe(
			[]bson.M{bson.M{"$group": bson.M{"_id": "$source"}}},
		).All(&sources)

		for _, source := range sources {
			row = sheet.AddRow()
			cell = row.AddCell()
			cell.Value = source.Name

			row = sheet.AddRow()
			for _, h_cell := range []string{"Телефон", "Статус", "Дата", "Стоимость", "Адрес подачи", "Адрес назначения", "Позывной автомобиля", "ФИО водителя"} {
				cell = row.AddCell()
				cell.Value = h_cell
			}

			orders, err := db.Orders.GetBy(bson.M{"source": source.Name})
			if err != nil {
				log.Printf("Error at getting orders from %+v is: %v", config.Main.Database, err)
				return err
			}

			for _, order := range orders {
				log.Printf("adding row for order %+v", order)
				user, u_err := db.Users.GetUserById(order.Whom)
				if u_err != nil || user == nil {
					log.Printf("No user found at id: %v", order.Whom)
					continue
				}
				row = sheet.AddRow()

				ph_c := row.AddCell()
				ph_c.SetString(user.Phone)

				stat_c := row.AddCell()
				if state, ok := t.InfinityStatusesName[order.OrderState]; ok {
					stat_c.SetString(state)
				} else {
					stat_c.SetString("Не определен")
				}

				time_c := row.AddCell()
				time_c.SetDateTime(order.When)

				if len(order.OrderData.Content) > 0 {
					log.Printf("we have additional data of order %v", order.OrderId)
					cost := order.OrderData.Get("Cost")
					if cost != nil {
						cost_c := row.AddCell()
						cost_c.SetInt(order.OrderData.Get("Cost").(int))

						deliv_c := row.AddCell()
						deliv_c.SetString(order.OrderData.Get("DeliveryStr").(string))

						dest_c := row.AddCell()
						dest_c.SetString(order.OrderData.Get("DestinationsStr").(string))

						car_c := row.AddCell()
						car_c.SetString(order.OrderData.Get("Car").(string))

						driver_c := row.AddCell()
						driver_c.SetString(order.OrderData.Get("Drivers").(string))
					}
				}
				log.Printf("Added row: %+v", row)
			}
		}
	}
	fName := fmt.Sprintf("%v/statistic.xlsx", toPath)
	file.Save(fName)
	return nil
}
func TestTaxiInfinityFail(t *testing.T) {
	conf := c.ReadTestConfigInRecursive()
	db := d.NewMainDb(conf.Main.Database.ConnString, conf.Main.Database.Name)
	taxi_conf := conf.Taxis["fake"]

	t.Logf("taxi api configuration for %+v:\n%v", taxi_conf.Name, taxi_conf.Api)
	external := i.GetTestInfAPI(taxi_conf.Api)

	external_api := external.(taxi.TaxiInterface)
	external_address_supplier := external.(taxi.AddressSupplier)

	apiMixin := taxi.ExternalApiMixin{API: external_api}

	carsCache := taxi.NewCarsCache(external_api)
	notifier := n.NewNotifier(conf.Main.CallbackAddr, taxi_conf.Chat.Key, db)

	address_handler, address_supplier := GetAddressInstruments(conf, taxi_conf.Name, external_address_supplier)
	configStore := d.NewConfigurationStorage(conf.Main.ConfigDatabase)
	botContext := taxi.FormTaxiBotContext(&apiMixin, db, configStore, taxi_conf, address_handler, carsCache)
	controller := m.FormBotController(botContext, db)

	t.Logf("Was create bot context: %+v\n", botContext)
	http.HandleFunc(fmt.Sprintf("/taxi/%v", taxi_conf.Name), controller)

	go func() {
		taxiContext := taxi.TaxiContext{API: external_api, DataBase: db, Cars: carsCache, Notifier: notifier}
		t.Logf("Will start order watcher for [%v]", botContext.Name)
		taxi.TaxiOrderWatch(&taxiContext, botContext)
	}()

	http.HandleFunc(fmt.Sprintf("/taxi/%v/streets", taxi_conf.Name), func(w http.ResponseWriter, r *http.Request) {
		geo.StreetsSearchController(w, r, address_supplier)
	})

	go func() {
		server_address := fmt.Sprintf(":%v", conf.Main.Port)
		t.Logf("\nStart listen and serving at: %v\n", server_address)
		server := &http.Server{
			Addr: server_address,
		}
		server.ListenAndServe()
	}()

	u.After(external_api.IsConnected, func() {
		inf_api := external.(*i.InfinityAPI)
		for i, _ := range inf_api.ConnStrings {
			inf_api.ConnStrings[i] += "w"
		}
	})

	_, err := u.GET(taxi_conf.DictUrl, &map[string]string{"q": "лесос"})
	if err != nil {
		t.Error("Error at getting street %v", err)
	}

	out_res, err := tu.POST(fmt.Sprintf("http://localhost:%v/taxi/%v", conf.Main.Port, taxi_conf.Name), &structs.InPkg{
		Message: &structs.InMessage{
			ID: u.GenStringId(),
			Commands: &[]structs.InCommand{
				structs.InCommand{Action: "information", Title: "information"},
			},
		},
		From:     "test user",
		UserData: &structs.InUserData{Name: "TEST"},
	})

	if err != nil {
		t.Errorf("Error at unmarshal result info %v", err)
	}

	if out_res == nil {
		t.Error("Out info result is nil!")
	} else {
		if out_res.Message.Type != "chat" {
			t.Errorf("Out message type != chat, but == %v", out_res.Message.Type)
		}
		ch, _ := configStore.GetChatConfig(taxi_conf.Chat.CompanyId)

		if out_res.Message.Body != ch.Information {
			t.Errorf("Out message body != info in config, but == %v", out_res.Message.Body)
		}
	}

}
func TestLogInOut(t *testing.T) {
	conf := c.ReadConfig()
	d.DELETE_DB = true
	if d.DELETE_DB {
		log.Println("!start at test mode!")
		conf.Main.Database.Name = conf.Main.Database.Name + "_test"
	}

	user, pwd := "test", "test"

	db := d.NewMainDb(conf.Main.Database.ConnString, conf.Main.Database.Name)
	err := db.Users.SetUserPassword(user, pwd)
	if err != nil {
		go func() {
			for err == nil {
				time.Sleep(1 * time.Second)
				err = db.Users.SetUserPassword(user, pwd)
				log.Printf("trying add user for test shops... now we have err:%+v", err)
			}
		}()
	}

	for _, shop_conf := range conf.Shops {
		if shop_conf.Name != "test_shop" {
			continue
		}

		db := d.NewMainDb(conf.Main.Database.ConnString, conf.Main.Database.Name)
		for !db.IsConnected() {
			log.Printf("wait wile db is connected...")
			time.Sleep(1 * time.Second)
		}
		bot_context := FormShopCommands(db, &shop_conf)
		request_commands := bot_context.RequestProcessors
		message_commands := bot_context.MessageProcessors

		in := s.InPkg{From: "TEST", UserData: &s.InUserData{Phone: "TEST123"}, Request: &s.InRequest{ID: "1234", Type: "get"}}
		in.Request.Query.Action = "COMMANDS"

		request_result := request_commands["commands"].ProcessRequest(&in)
		rr_commands := *request_result.Commands
		log.Printf("request commands result: %#v", reflect.DeepEqual(rr_commands, NOT_AUTH_COMMANDS))

		if !reflect.DeepEqual(rr_commands, NOT_AUTH_COMMANDS) {
			t.Errorf("before auth commands is auth")
		}

		in_auth := s.InPkg{
			From:     "TEST",
			UserData: &s.InUserData{Phone: "TEST123"},
			Message: &s.InMessage{Commands: &[]s.InCommand{
				s.InCommand{
					Action: "authorise",
					Form: s.InForm{
						Fields: []s.InField{
							s.InField{
								Name: "username",
								Data: s.InFieldData{
									Value: "test",
								},
							},
							s.InField{
								Name: "password",
								Data: s.InFieldData{
									Value: "test",
								},
							},
						}},
				},
			}}}
		auth_result := message_commands["authorise"].ProcessMessage(&in_auth)
		ar_commnads := *auth_result.Commands
		log.Printf("auth commands result: %v", reflect.DeepEqual(ar_commnads, AUTH_COMMANDS))
		if !reflect.DeepEqual(ar_commnads, AUTH_COMMANDS) {
			t.Errorf("after auth result commands is not aut")
		}
		log.Println("request commands next...")
		request_result = request_commands["commands"].ProcessRequest(&in)
		rr_commands = *request_result.Commands
		log.Printf("request commands result: %#v", reflect.DeepEqual(rr_commands, AUTH_COMMANDS))
		if !reflect.DeepEqual(rr_commands, AUTH_COMMANDS) {
			t.Errorf("after auth commands not auth")
		}

	}
}