func (oh *OwnAddressHandler) form_own_autocomplete_result(query elastic.Query, sort_by elastic.Sorter) []t.AddressF {
	rows := []t.AddressF{}
	s_result, err := oh.client.Search().Index("autocomplete").Query(query).Size(1000).SortBy(sort_by).Pretty(true).Do()
	if err != nil {
		log.Printf("error in own address handler search at search in elastic: \n%v", err)
		return rows
	}
	log.Printf("OWN Found %v in index", s_result.TotalHits())

	var oae OsmAutocompleteEntity
	name_city_set := s.NewSet()
	for _, osm_hit := range s_result.Each(reflect.TypeOf(oae)) {
		if entity, ok := osm_hit.(OsmAutocompleteEntity); ok {
			street_name, street_type := GetStreetNameAndShortName(entity.Name)
			entity_hash := fmt.Sprintf("%v%v%v", street_name, street_type, entity.City)
			if !name_city_set.Contains(entity_hash) && street_type != "" {
				addr := t.AddressF{
					Name:      street_name,
					ShortName: street_type,
					OSM_ID:    entity.OSM_ID,
					City:      entity.City,
				}
				rows = append(rows, addr)
				name_city_set.Add(entity_hash)
			}
		}
	}
	return rows
}
func _get_address_set(sl []t.AddressF, info map[string]t.AddressF) s.Set {
	result := s.NewSet()
	for _, el := range sl {
		ah := _addr_hash(el)
		info[ah] = el
		result.Add(ah)
	}
	return result
}
func (oh *OwnAddressHandler) GetExternalInfo(key, name string) (*t.AddressF, error) {
	log.Printf("OWN Will getting external info of %v [%v]", name, key)
	t_query := elastic.NewTermQuery("osm_id", key)
	s_result, err := oh.client.Search().Index("photon").Query(t_query).Do()
	if err != nil {
		log.Printf("error in own address handler search at search in elastic %v", err)
	}
	var ogcr OwnGeoCodeResult
	for _, osm_hit := range s_result.Each(reflect.TypeOf(ogcr)) {
		if entity, ok := osm_hit.(OwnGeoCodeResult); ok {
			local_set := s.NewSet()
			_name := clear_address_string(entity.Name.GetAny())
			add_to_set(local_set, _name)
			add_to_set(local_set, clear_address_string(entity.City.GetAny()))

			log.Printf("OWN Query to external: |%v| \nlocal set: %+v", _name, local_set)

			rows := oh.ExternalAddressSupplier.AddressesAutocomplete(_name).Rows
			if IO_REGEXP.MatchString(_name) {
				rows_io := oh.ExternalAddressSupplier.AddressesAutocomplete(_correct_io(_name)).Rows
				if rows_io != nil {
					if rows == nil {
						rows = rows_io
					} else {
						e_rows_io := *rows_io
						e_rows := *rows
						e_rows = append(e_rows, e_rows_io...)
						rows = &e_rows
					}
					local_set.Remove(_name)
					local_set.Add(_correct_io(_name))
				}
			}

			if rows == nil {
				return nil, errors.New(fmt.Sprintf("система такси не знает местонахождение %v", _name))
			}
			ext_rows := *rows

			for i := len(ext_rows) - 1; i >= 0; i-- {
				nitem := ext_rows[i]
				ext_set := GetSetOfAddressF(nitem)
				log.Printf("OWN external set: %+v < ? > Local set %+v ", ext_set, local_set)
				if ext_set.IsSuperset(local_set) || local_set.IsSuperset(ext_set) {
					return &nitem, nil
				}
			}
		}
	}
	return nil, errors.New(fmt.Sprintf("не найдено ничего похожее на %v", name))

}
func (oh *OwnAddressHandler) autocomplete_rows(q string) []t.AddressF {
	result_sets := map[string]s.Set{}
	weghts := map[int64]float64{}
	info := map[string]t.AddressF{}
	all_found_addresses := []t.AddressF{}

	query := _correct_io(q)
	q_words := SPLIT_REGEXP.Split(query, -1)

	for _, word := range q_words {
		t_query := elastic.NewTermQuery("name", word)
		filter := elastic.NewGeoDistanceFilter("location").Distance("75km").Lat(oh.orbit.Lat).Lon(oh.orbit.Lon)
		query := elastic.NewFilteredQuery(t_query).Filter(filter)
		q_sort := elastic.NewGeoDistanceSort("location").Order(true).Point(oh.orbit.Lat, oh.orbit.Lon).Unit("km").SortMode("min").Asc()
		q_result := oh.form_own_autocomplete_result(query, q_sort)

		result_sets[word] = _get_address_set(q_result, info)
		all_found_addresses = append(all_found_addresses, q_result...)
	}
	for _, word := range q_words {
		for _, addr := range all_found_addresses {
			new_weight := oh.get_weight(addr, word)
			if weight, ok := weghts[addr.OSM_ID]; ok {
				new_weight += weight
			}
			weghts[addr.OSM_ID] = new_weight
		}
	}
	result := []t.AddressF{}
	if len(result_sets) == 1 {
		if set, ok := result_sets[query]; ok {
			result = _get_address_slice(set, info)
		}
	} else {
		intersect := s.NewSet()
		for _, set := range result_sets {
			if set.Cardinality() == 0 {
				continue
			}
			if intersect.Cardinality() == 0 {
				intersect = set
			}
			intersect = set.Intersect(intersect)
		}
		result = _get_address_slice(intersect, info)
	}
	return _sort_addresses(result, weghts)
}
func assert_not_duplicates(input []g.DictItem) bool {
	s_el := func(i g.DictItem) string {
		return fmt.Sprintf("%v%v%v", i.Key, i.Title, i.SubTitle)
	}
	input_set := set.NewSet()
	for _, el := range input {
		if input_set.Contains(s_el(el)) {
			log.Printf("%v have duplicate", el)
			return false
		} else {
			input_set.Add(s_el(el))
		}
	}
	log.Printf("OK not duplicates")
	return true
}
func _process_address_components(components []GoogleAddressComponent) (string, s.Set) {
	var route string
	google_set := s.NewSet()
	for _, component := range components {
		if u.IntersectionS(NOT_IMPLY_TYPES, component.Types) {
			//			log.Printf("component type %+v \ncontains not imply types: %v", component, component.Types)
			continue
		} else {
			long_name, err := AddStringToSet(google_set, component.LongName)
			if err != nil {
				log.Printf("WARN AT PROCESSING ADRESS COMPONENTS: %v", err)
				continue
			}
			if u.InS("route", component.Types) {
				route = long_name
			}
		}
	}
	return route, google_set
}