func (uh *UserHandler) CheckUserPassword(username, password string) (bool, error) {
	if !uh.parent.Check() {
		return false, errors.New("БД не доступна")
	}
	tmp := UserData{}
	err := uh.UsersCollection.Find(bson.M{"user_name": username, "password": u.PHash(password)}).One(&tmp)
	return err != nil, err
}
func (uh *UserHandler) SetUserPassword(username, password string) error {
	if !uh.parent.Check() {
		return errors.New("БД не доступна")
	}
	tmp, _ := uh.GetUser(bson.M{"user_name": username})
	if tmp == nil {
		err := uh.UsersCollection.Insert(&UserData{UserId: username, UserName: username, Password: u.PHash(password), LastUpdate: time.Now()})
		return err
	} else if u.PHash(password) != tmp.Password {
		log.Println("changing password! for user ", username)
		err := uh.UsersCollection.Update(
			bson.M{"user_name": username},
			bson.M{"$set": bson.M{"password": u.PHash(password), "last_update": time.Now()}},
		)
		return err
	}
	return nil
}
func StartBot(db *d.MainDb, result chan string) c.Configuration {
	conf := c.ReadConfig()
	log.Printf("configuration for db:\nconnection string: %+v\ndatabase name: %+v", conf.Main.Database.ConnString, conf.Main.Database.Name)
	log.Printf("configuration for conf db:\nconnection string: %+v\ndatabase name: %+v", conf.Main.ConfigDatabase.ConnString, conf.Main.ConfigDatabase.Name)
	db.Users.AddOrUpdateUserObject(d.UserData{
		UserId:    "alesha",
		UserName:  "******",
		Password:  utils.PHash("sederfes100500"),
		Role:      users.MANAGER,
		BelongsTo: "klichat",
	})
	configStorage := d.NewConfigurationStorage(conf.Main.ConfigDatabase)
	questStorage := q.NewQuestStorage(conf.Main.Database.ConnString, conf.Main.Database.Name)

	fs := http.FileServer(http.Dir("static"))
	http.Handle("/static/", http.StripPrefix("/static/", fs))

	for taxi_name, taxi_conf := range conf.Taxis {
		log.Printf("taxi api configuration for %+v:\n%v", taxi_conf.Name, taxi_conf.Api)
		external_api, external_address_supplier, err := GetTaxiAPIInstruments(taxi_conf.Api, taxi_name)

		if err != nil {
			log.Printf("Skip this taxi api [%+v]\nBecause: %v", taxi_conf.Api, err)
			continue
		}

		apiMixin := t.ExternalApiMixin{API: external_api}

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

		address_handler, address_supplier := GetAddressInstruments(conf, taxi_name, external_address_supplier)

		botContext := t.FormTaxiBotContext(&apiMixin, db, configStorage, taxi_conf, address_handler, carsCache)
		controller := m.FormBotController(botContext, db)

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

		go func() {
			api, err := GetTaxiAPI(taxi_conf.Api, taxi_name+"_watch")
			if err != nil {
				log.Printf("Error at get api: %v for %v, will not use order watching", err, taxi_name)
			}
			cc := t.NewCarsCache(api)
			taxiContext := t.TaxiContext{API: api, DataBase: db, Cars: cc, Notifier: notifier}
			log.Printf("Will start order watcher for [%v]", botContext.Name)
			t.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)
		})
		if m.TEST {
			http.HandleFunc(fmt.Sprintf("/taxi/%v/streets/ext", taxi_conf.Name), func(w http.ResponseWriter, r *http.Request) {
				geo.StreetsSearchController(w, r, external_address_supplier)
			})
		}

		configStorage.SetChatConfig(taxi_conf.Chat, false)

		result <- fmt.Sprintf("taxi_%v", taxi_name)
	}

	for _, shop_conf := range conf.Shops {
		bot_context := sh.FormShopCommands(db, &shop_conf)
		shop_controller := m.FormBotController(bot_context, db)
		http.HandleFunc(fmt.Sprintf("/shop/%v", shop_conf.Name), shop_controller)
		result <- fmt.Sprintf("shops_%v", shop_conf.Name)
	}

	if conf.RuPost.WorkUrl != "" {
		log.Printf("will start ru post controller at: %v and will send requests to: %v", conf.RuPost.WorkUrl, conf.RuPost.ExternalUrl)
		rp_bot_context := rp.FormRPBotContext(conf)
		rp_controller := m.FormBotController(rp_bot_context, db)
		http.HandleFunc(conf.RuPost.WorkUrl, rp_controller)
		result <- "rupost"
	}

	for _, qConf := range conf.Quests {
		q_name := qConf.Chat.CompanyId
		log.Printf("Will handling quests controller for quest: %v", q_name)
		qb_controller := q.FormQuestBotContext(conf, qConf, questStorage, db, configStorage)
		q_controller := m.FormBotController(qb_controller, db)
		route := fmt.Sprintf("/quest/%v", q_name)
		log.Printf("Quest %v will handle at %v", q_name, route)
		http.HandleFunc(route, q_controller)

		configStorage.SetChatConfig(qConf.Chat, false)
		questStorage.SetMessageConfiguration(q.QuestMessageConfiguration{CompanyId: qConf.Chat.CompanyId}, false)

		result <- fmt.Sprintf("quest_%v", q_name)
	}
	if conf.Console.WebPort != "" && conf.Console.Chat.Key != "" {
		log.Printf("Will handling requests from /console at %v", conf.Console.WebPort)
		bc := cnsl.FormConsoleBotContext(conf, db, configStorage)
		cc := m.FormBotController(bc, db)
		http.HandleFunc("/console", cc)

		web.DefaultUrlMap.AddAccessory("klichat", "/klichat")

		configStorage.SetChatConfig(conf.Console.Chat, false)

		result <- "console"
	}

	if conf.Vote.DictUrl != "" {
		vdh, _ := v.NewVotingHandler(conf.Main.Database.ConnString, conf.Main.Database.Name)
		http.HandleFunc("/autocomplete/vote/name", func(w http.ResponseWriter, r *http.Request) {
			v.AutocompleteController(w, r, vdh, "name", []string{})
		})
		http.HandleFunc("/autocomplete/vote/city", func(w http.ResponseWriter, r *http.Request) {
			v.AutocompleteController(w, r, vdh, "city", conf.Vote.Cities)
		})
		http.HandleFunc("/autocomplete/vote/service", func(w http.ResponseWriter, r *http.Request) {
			v.AutocompleteController(w, r, vdh, "service", conf.Vote.Services)
		})
		http.HandleFunc("/autocomplete/vote/role", func(w http.ResponseWriter, r *http.Request) {
			v.AutocompleteController(w, r, vdh, "vote.voters.role", conf.Vote.Roles)
		})

		voteBot := v.FormVoteBotContext(conf, db)
		voteBotController := m.FormBotController(voteBot, db)
		log.Printf("Will handling requests for /vote")
		http.HandleFunc("/vote", voteBotController)
		result <- "vote"
	}

	if len(conf.Coffee) > 0 {
		for _, coffee_conf := range conf.Coffee {
			c_store := coffee.NewCoffeeConfigHandler(db)
			c_store.LoadFromConfig(coffee_conf)
			coffeeHouseConfiguration := coffee.NewCHCFromConfig(coffee_conf)

			cbc := coffee.FormBotCoffeeContext(coffee_conf, db, coffeeHouseConfiguration, configStorage)
			cntrl := m.FormBotController(cbc, db)
			route := fmt.Sprintf("/bot/coffee/%v", coffee_conf.Chat.CompanyId)
			http.HandleFunc(route, cntrl)
			log.Printf("will handling bot messages for coffee %v at %v", coffee_conf.Chat.CompanyId, route)

			http.HandleFunc(fmt.Sprintf("/autocomplete/coffee/%v/drink", coffee_conf.Chat.CompanyId), func(w http.ResponseWriter, r *http.Request) {
				coffee.AutocompleteController(w, r, c_store, "drinks", coffee_conf.Chat.CompanyId)
			})

			http.HandleFunc(fmt.Sprintf("/autocomplete/coffee/%v/volume", coffee_conf.Chat.CompanyId), func(w http.ResponseWriter, r *http.Request) {
				coffee.AutocompleteController(w, r, c_store, "volumes", coffee_conf.Chat.CompanyId)
			})

			http.HandleFunc(fmt.Sprintf("/autocomplete/coffee/%v/bake", coffee_conf.Chat.CompanyId), func(w http.ResponseWriter, r *http.Request) {
				coffee.AutocompleteController(w, r, c_store, "bakes", coffee_conf.Chat.CompanyId)
			})

			http.HandleFunc(fmt.Sprintf("/autocomplete/coffee/%v/additive", coffee_conf.Chat.CompanyId), func(w http.ResponseWriter, r *http.Request) {
				coffee.AutocompleteController(w, r, c_store, "additives", coffee_conf.Chat.CompanyId)
			})
			var salt string
			if coffee_conf.Chat.UrlSalt != "" {
				salt = fmt.Sprintf("%v-%v", coffee_conf.Chat.CompanyId, coffee_conf.Chat.UrlSalt)
			} else {
				salt = coffee_conf.Chat.CompanyId
			}

			notifier := n.NewNotifier(conf.Main.CallbackAddr, coffee_conf.Chat.Key, db)
			notifier.SetFrom(coffee_conf.Chat.CompanyId)

			webRoute := fmt.Sprintf("/web/coffee/%v", salt)
			http.Handle(webRoute, coffee.GetChatMainHandler(webRoute, notifier, db, coffee_conf.Chat))
			web.DefaultUrlMap.AddAccessory(coffee_conf.Chat.CompanyId, webRoute)

			sr := func(s string) string {
				return fmt.Sprintf("%v%v", webRoute, s)
			}
			http.Handle(sr("/send"), chat.GetChatSendHandler(sr("/send"), notifier, db, coffee_conf.Chat, chat.NewChatStorage(db)))
			http.Handle(sr("/unread_messages"), chat.GetChatUnreadMessagesHandler(sr("/unread_messages"), notifier, db, coffee_conf.Chat))
			http.Handle(sr("/messages_read"), chat.GetChatMessageReadHandler(sr("/messages_read"), notifier, db, coffee_conf.Chat))
			http.Handle(sr("/contacts_change"), chat.GetChatContactsChangeHandler(sr("/contacts_change"), notifier, db, coffee_conf.Chat))
			http.Handle(sr("/delete_messages"), chat.GetChatDeleteMessagesHandler(sr("/delete_messages"), db, coffee_conf.Chat))

			http.Handle(sr("/config"), coffee.GetChatConfigHandler(sr("/config"), webRoute, db, coffee_conf.Chat))
			http.Handle(sr("/contacts"), coffee.GetChatContactsHandler(sr("/contacts"), notifier, db, coffee_conf.Chat))
			http.Handle(sr("/message_function"), coffee.GetMessageAdditionalFunctionsHandler(sr("/message_function"), notifier, db, coffee_conf.Chat, coffeeHouseConfiguration))
			//http.Handle(sr("/order_page"), coffee.GetOrdersPageFunctionHandler(sr("/order_page"), webRoute, db, coffee_conf.Chat, coffee_conf.Chat.CompanyId))
			//http.Handle(sr("/order_page_supply"), coffee.GetOrdersPageSupplierFunctionHandler(sr("/order_page_supply"), webRoute, db, coffee_conf.Chat, coffee_conf.Chat.CompanyId))
			http.Handle(sr("/logout"), coffee.GetChatLogoutHandler(sr("/logout"), webRoute, db, coffee_conf.Chat))

			log.Printf("I will handling web requests for coffee %v at : [%v]", coffee_conf.Chat.CompanyId, webRoute)
			db.Users.AddOrUpdateUserObject(d.UserData{
				UserId:      coffee_conf.Chat.User,
				UserName:    coffee_conf.Chat.User,
				ShowedName:  coffee_conf.Chat.Name,
				Password:    utils.PHash(coffee_conf.Chat.Password),
				BelongsTo:   coffee_conf.Chat.CompanyId,
				ReadRights:  []string{coffee_conf.Chat.CompanyId},
				WriteRights: []string{coffee_conf.Chat.CompanyId},
			})

			configStorage.SetChatConfig(coffee_conf.Chat, false)
		}
		result <- "coffee"
	}
	if len(conf.Chats) > 0 {
		for _, chat_conf := range conf.Chats {

			chatBotContext := chat.FormChatBotContext(db, configStorage, chat_conf.CompanyId)
			chatBotController := m.FormBotController(chatBotContext, db)
			route := fmt.Sprintf("/bot/chat/%v", chat_conf.CompanyId)
			http.HandleFunc(route, chatBotController)
			log.Printf("I will serving message for chat bot at : [%v]", route)

			notifier := n.NewNotifier(conf.Main.CallbackAddr, chat_conf.Key, db)
			notifier.SetFrom(chat_conf.CompanyId)

			var salt string
			if chat_conf.UrlSalt != "" {
				salt = fmt.Sprintf("%v-%v", chat_conf.CompanyId, chat_conf.UrlSalt)
			} else {
				salt = chat_conf.CompanyId
			}
			webRoute := fmt.Sprintf("/web/chat/%v", salt)
			http.Handle(webRoute, chat.GetChatMainHandler(webRoute, notifier, db, chat_conf))
			web.DefaultUrlMap.AddAccessory(chat_conf.CompanyId, webRoute)

			sr := func(s string) string {
				return fmt.Sprintf("%v%v", webRoute, s)
			}
			http.Handle(sr("/send"), chat.GetChatSendHandler(sr("/send"), notifier, db, chat_conf, chat.NewChatStorage(db)))
			http.Handle(sr("/unread_messages"), chat.GetChatUnreadMessagesHandler(sr("/unread_messages"), notifier, db, chat_conf))
			http.Handle(sr("/messages_read"), chat.GetChatMessageReadHandler(sr("/messages_read"), notifier, db, chat_conf))
			http.Handle(sr("/contacts"), chat.GetChatContactsHandler(sr("/contacts"), notifier, db, chat_conf))
			http.Handle(sr("/contacts_change"), chat.GetChatContactsChangeHandler(sr("/contacts_change"), notifier, db, chat_conf))
			http.Handle(sr("/config"), chat.GetChatConfigHandler(sr("/config"), webRoute, db, chat_conf))
			http.Handle(sr("/delete_messages"), chat.GetChatDeleteMessagesHandler(sr("/delete_messages"), db, chat_conf))
			http.Handle(sr("/logout"), chat.GetChatLogoutHandler(sr("/logout"), webRoute, db, chat_conf))

			log.Printf("I will handling web requests for chat at : [%v]", webRoute)

			db.Users.AddOrUpdateUserObject(d.UserData{
				UserName:    chat_conf.User,
				Password:    utils.PHash(chat_conf.Password),
				UserId:      chat_conf.User,
				BelongsTo:   chat_conf.CompanyId,
				ReadRights:  []string{chat_conf.CompanyId},
				WriteRights: []string{chat_conf.CompanyId},
			})

			configStorage.SetChatConfig(chat_conf, false)
		}
		result <- "chat"
	}

	go n.WatchUnreadMessages(db, configStorage, conf.Main.CallbackAddrMembers)
	go autoanswers.WatchNotAnsweredMessages(db, configStorage, conf.Main.CallbackAddr)

	server_address := fmt.Sprintf(":%v", conf.Main.Port)
	log.Printf("\nStart listen and serving at: %v\n", server_address)
	server := &http.Server{
		Addr: server_address,
	}
	result <- "listen"
	http.Handle("/", web.NewSessionAuthorisationHandler(db))
	log.Fatal(server.ListenAndServe())
	return conf
}
func (uh *UserHandler) LoginUser(userName, password string) (*UserData, error) {
	tmp := UserData{}
	err := uh.UsersCollection.Find(bson.M{"$or": []bson.M{bson.M{"user_name": userName}, bson.M{"email": userName}}, "password": utils.PHash(password)}).One(&tmp)
	log.Printf("UH INFO: found data: %+v", tmp)
	if err == nil {
		log.Printf("UH INFO: for user: %+v set auth true", tmp)
		err = uh.UsersCollection.UpdateId(tmp.ID.Hex(), bson.M{"$set": bson.M{"auth": true, "last_logged": time.Now().Unix()}})
		log.Printf("UH update err? %v", err)
		err = uh.UsersCollection.FindId(tmp.ID).One(&tmp)
		log.Printf("UH INFO: UpDATE err: %v after objet: \n%+v", err, tmp)
		return &tmp, err
	} else {
		log.Printf("UH WARN! USER NOT AUTH IN DB, because: %v", err)
	}
	return nil, err
}
func EnsureWorkWithUsers(r martini.Router, db *d.MainDb) martini.Router {
	r.Group("/users", func(r martini.Router) {
		r.Get("", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(r render.Render, req *http.Request) {
			r.HTML(200, "users", w.AddCurrentUser(GetUsersInfo("", db), req, db), render.HTMLOptions{Layout: "base"})
		})

		r.Post("/add", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(r render.Render, request *http.Request) {
			u_id := strings.TrimSpace(request.FormValue("user-id"))
			u_name := strings.TrimSpace(request.FormValue("user-name"))
			u_phone := request.FormValue("user-phone")
			u_email := request.FormValue("user-e-mail")
			u_role := strings.TrimSpace(request.FormValue("user-role"))
			u_pwd := request.FormValue("user-pwd")
			u_read_rights := strings.Fields(request.FormValue("read-rights"))
			u_write_rights := strings.Fields(request.FormValue("write-rights"))
			u_belongs_to := strings.TrimSpace(request.FormValue("belongs-to"))

			log.Printf("CONSOLE WEB add user [%s]  '%s' +%s %s |%v| {%s}", u_id, u_name, u_phone, u_email, u_role, u_pwd)
			if u_name != "" && u_id != "" {
				db.Users.AddOrUpdateUserObject(d.UserData{
					UserId:      u_id,
					UserName:    u_name,
					Email:       u_email,
					Phone:       u_phone,
					Role:        u_role,
					Password:    u.PHash(u_pwd),
					LastUpdate:  time.Now(),
					ReadRights:  u_read_rights,
					WriteRights: u_write_rights,
					BelongsTo:   u_belongs_to,
				})
				r.Redirect("/users")
			} else {
				r.HTML(200,
					"users",
					w.AddCurrentUser(GetUsersInfo("Невалидные значения имени и (или) идентификатора добавляемого пользователя", db), request, db),
					render.HTMLOptions{Layout: "base"})
			}
		})

		r.Post("/delete/:id", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(params martini.Params, render render.Render) {
			uid := params["id"]
			err := db.Users.UsersCollection.Remove(bson.M{"user_id": uid})
			log.Printf("CONSOLE WEB will delete user %v (%v)", uid, err)
			render.Redirect("/users")
		})

		r.Post("/update/:id", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(params martini.Params, render render.Render, request *http.Request) {
			u_id := params["id"]
			u_name := strings.TrimSpace(request.FormValue("user-name"))
			u_phone := request.FormValue("user-phone")
			u_email := request.FormValue("user-e-mail")
			u_role := request.FormValue("user-role")
			u_pwd := request.FormValue("user-pwd")
			u_read_rights := strings.Fields(request.FormValue("read-rights"))
			u_write_rights := strings.Fields(request.FormValue("write-rights"))
			u_belongs_to := strings.TrimSpace(request.FormValue("belongs-to"))

			upd := bson.M{}
			if u_name != "" {
				upd["user_name"] = u_name
			}
			if u_email != "" {
				upd["email"] = u_email
			}
			if u_phone != "" {
				upd["phone"] = u_phone
			}
			if u_role != "" {
				upd["role"] = u_role
			}
			if u_pwd != "" {
				upd["password"] = u.PHash(u_pwd)
			}
			if len(u_read_rights) > 0 {
				upd["read_rights"] = u_read_rights
			}
			if len(u_write_rights) > 0 {
				upd["write_rights"] = u_write_rights
			}
			if u_belongs_to != "" {
				upd["belongs_to"] = u_belongs_to
			}
			db.Users.UsersCollection.Update(bson.M{"user_id": u_id}, bson.M{"$set": upd})
			log.Printf("CONSOLE WEB update user [%s]  '%s' +%s %s |%v| {%v}", u_id, u_name, u_phone, u_email, u_role, u_pwd)
			render.Redirect("/users")
		})
	})
	return r
}