placeController2 = Class.create({
  initialize: function() {
    this.name = String(Math.random()).substring(2, 15);
    this.id = {
      country:null,
      state:null,
      county:null,
      city:null,
      place:null
    };
    this.text = {
      country:'',
      state:'',
      city:'',
      county:'',
      place:''
    };
    this.recognizedText = {
      country:'',
      state:'',
      city:'',
      county:'',
      place:''
    };
    this.complete = {
      'country':{'us':'United States','usa':'United States'},
      'state':{},
      'conty':{},
      'city':{},
      'place':{}
    };
  },

  hashOnChange: 0,

  initValue: function(request_id) {
    if (!this._idReady()) {
      alert('You can\'t init Place Control, until register all required elements.')
    }
    request_id = parseInt(request_id);
    if(this.defaultValue && !request_id){
      request_id = this.defaultValue;
    }
    if (request_id > 0) {
      this.options = {};
      this.options.asynchronous = true;
      this.options.onComplete = this._onCompleteInitValue.bind(this);
      var result = {
        hash: String(Math.random()).substring(2, 15),
        request: 'all',
        id: {
          req_place: request_id
        }
      };
      this.options.parameters = "r=" + Object.toJSON(result);
      new Ajax.Request("/places/get_place/", this.options);
    }
  },

  _onCompleteInitValue: function(request) {
    var response = request.responseText.evalJSON()
    if (response.status == 0) {
      var object = response.result.value[0];
      if (object.ci && object.cn) {
        this.setControlValue('country', object.ci, object.cn);
        this.setControlText('country', object.cn);
        //this._addActiveMarker_('city');
      }
      if (this.flagImg && object.ciso) {
        this.flagImg.src = '/media/flags/' + object.ciso.toLowerCase() + '.png';
      }
      if (object.si && object.sn) {
        this.setControlValue('state', object.si, object.sn);
        this.setControlText('state', object.sn);
        //this._addActiveMarker_('city');
      }
      if (object.cii && object.cin) {
        this.setControlValue('city', object.cii, object.cin);
        this.setControlText('city', object.cin);
        //this._addActiveMarker_('city');
      }
      if (object.coi && object.con) {
        this.setControlValue('county', object.coi, object.con);
        if (this.id.city != null) {
          this.setControlText('city', object.cin + ' (' + object.con + ' County)');
        } else {
          this.setControlText('city', object.con + ' County');
        }
        //this._addActiveMarker_('city');
      }
      this._render();
    }
  },

  register: function(params) {
    for (var key in  params) {
      var value = params[key];
      switch (key) {
        case 'countryInput':
          var div = document.body.appendChild(new Element('div', {
            'class': 'autocomplete'
          }));
          this.countryAjaxInput = new placeControl2(value, div, "/places/get_place/");
          this.countryAjaxInput._controller = this;
          this.countryInput = this.countryAjaxInput.element;
          this.countryInput._controller = this;
          this._registerOnChange(this.countryInput);
          break;
        case 'stateInput':
          var div = document.body.appendChild(new Element('div', {
            'class': 'autocomplete'
          }));
          this.stateAjaxInput = new placeControl2(value, div, "/places/get_place/");
          this.stateAjaxInput._controller = this;
          this.stateInput = this.stateAjaxInput.element;
          this.stateInput._controller = this;
          this._registerOnChange(this.stateInput);
          break;
        case 'cityInput':
        //!!!
        //$(value).onkeydown = function(){this.city.element.parentNode.getElementsByTagName('A')[0].style.visibility = "visible";}
          var div = document.body.appendChild(new Element('div', {
            'class': 'autocomplete'
          }));
          this.cityAjaxInput = new placeControl2(value, div, "/places/get_place/");
          this.cityAjaxInput._controller = this;
          this.cityInput = this.cityAjaxInput.element;
          this.cityInput._controller = this;
          this._registerOnChange(this.cityInput);
          break;
        case 'countryClearButton':
          this.countryClearButton = $(value);
          this.countryClearButton.observe('click', this.onClear.bindAsEventListener(this));
          break;
        case 'stateClearButton':
          this.stateClearButton = $(value);
          this.stateClearButton.observe('click', this.onClear.bindAsEventListener(this));
          break;
        case 'cityClearButton':
          this.cityClearButton = $(value);
          this.cityClearButton.observe('click', this.onClear.bindAsEventListener(this));
          break;
        case 'countryContainer':
          this.countryContainer = $(value);
          this.countryContainer.addClassName('undefined');
          break;
        case 'stateContainer':
          this.stateContainer = $(value);
          this.stateContainer.addClassName('undefined');
          break;
        case 'cityContainer':
          this.cityContainer = $(value);
          this.cityContainer.addClassName('undefined');
          break;
        case 'resultInput':
          if ($(value)) {
            this.resultInput = $(value);
            this.initValue(this.resultInput.value);
          }
          break;
        case 'resultSearchInput':
          if ($(value)) {
            this.resultSearchInput = $(value);
          }
          break;
        case 'flagImg':
          this.flagImg = $(value);


          var self = this;
          this.flagImg.observe('click', function() {
            self.countryInput.focus();
          });


          break;
        case 'zoomInButton':
          this.zoomInButton = $(value);
          this.zoomInButton.observe('click', this.onZoomIn.bindAsEventListener(this));
          break;
        case 'zoomOutButton':
          this.zoomOutButton = $(value);
          this.zoomOutButton.observe('click', this.onZoomOut.bindAsEventListener(this));
          break;
        case 'defaultValue':
            this.defaultValue = value;
          break;
        default:
          break;
      }
    }
    this._render();
  },

  _registerOnChange: function(input) {
    //input.observe('input', this.onChangeDumper.bindAsEventListener(this));
    input.observe('paste', this.onChangeDumper.bindAsEventListener(this));
    input.observe('change', this.onChangeDumper.bindAsEventListener(this));
    input.observe('keyup', this.onChangeDumper.bindAsEventListener(this));
    input.observe('mouseup', this.onChangeDumper.bindAsEventListener(this));
  },

  _render: function() {
    if (this._idReady()) {
      this._disableIfNoCountry();
      this._dispalyResult();
    }
  },

  getValue: function() {
    var value = '';
    if (this.id.country != null) {
      value = this.id.country;
    }
    if (this.id.state != null) {
      value = this.id.state;
    }
    if (this.id.county != null) {
      value = this.id.county;
    }
    if (this.id.city != null) {
      value = this.id.city;
    }
    if (this.currentActivemarker && this.id[this.currentActivemarker]) {
      value = this.id[this.currentActivemarker];
    }
    return value;
  },

  onZoomIn: function() {
    if (this.id.country == null) {
      this._activateControl('country');
    } else if (this.id.state == null) {
      this._activateControl('state');
    } else if (this.id.city == null && this.id.county == null) {
      this._activateControl('city');
    }
    /*
    if (this.currentActivemarker){
      switch (this.currentActivemarker){
        case 'country':
          this._addActiveMarker_('state');
          break;
        case 'state':
          this._addActiveMarker_('city');
          break;
        case 'city':
        break;
      }
    }
    */
    this._render();
    this._dispalyResult();
  },

  onZoomOut: function() {
    if (this.id.city != null || this.id.county != null) {
      this.setControlValue('city', null, '');
      this.setControlValue('county', null, '');

      this.setControlText('city', '');
      this.setControlText('county', '');
    } else if (this.id.state != null) {
      this.setControlValue('state', null, '');
      this.setControlText('state', '');
    } else if (this.id.country != null) {
      this.setControlValue('country', null, '');
      this.setControlText('country', '');
    }
    /*
    if (this.currentActivemarker){
      switch (this.currentActivemarker){
        case 'country':
          break;
        case 'state':
          this._addActiveMarker_('country');
          break;
        case 'city':
          this._addActiveMarker_('state');
          break;
        break;
      }
    }
    */
    this._render();
    this._dispalyResult();
  },

  _disableIfNoCountry: function() {
    if (this.id.country == null) {
      this.stateContainer.addClassName('disabled');
      this.cityContainer.addClassName('disabled');
    } else {
      this.stateContainer.removeClassName('disabled');
      this.cityContainer.removeClassName('disabled');
    }
  },

  _dispalyResult: function() {
    var result = "";
    var resultSearch = [];
    if (this.id.country != null) {
      result += "Country = " + this.id.country + ", ";
      resultSearch.push("country:" + this.text.country);
    }
    if (this.id.state != null) {
      result += "State = " + this.id.state + ", ";
      resultSearch.push("state:" + this.text.state);
    }
    if (this.id.county != null) {
      result += "County = " + this.id.county + ", ";
      resultSearch.push("county:" + this.text.county);
    }
    if (this.id.city != null) {
      result += "City = " + this.id.city + ", ";
      resultSearch.push("city:" + this.text.city);
    }
    if ($('result')) {
      $('result').innerHTML = result;
    }
    if (this.resultSearchInput) {
      for (var i = 0; i < resultSearch.length; i++) {
        resultSearch[i] = resultSearch[i].toLowerCase().replace(/ /g, '_');
      }
      this.resultSearchInput.setValue(resultSearch.join(' AND '));
    }
    if (this.resultInput) {
      this.resultInput.setValue(this.getValue());
    }
  },

  setControlValue: function(type, id, text) {
    // set id  and  text
    this.id[type] = id;
    this.text[type] = text;
    //this.recognizedText[type] = text;
    if (id > 0) {
      if (type == 'county') {
        this['cityContainer'].removeClassName('undefined');
      } else {
        this[type + 'Container'].removeClassName('undefined');
      }
    }else{
      if (type == 'county') {
        this['cityContainer'].addClassName('undefined');
      } else {
        this[type + 'Container'].addClassName('undefined');
      }
    }

    switch (type) {
      case 'country':
        break;
    }
  },

  setControlText: function(type, text) {
    // set id  and  text
    if (type == 'county') {
      var input = this['cityInput'];
    } else {
      var input = this[type + 'Input'];
    }
    this.recognizedText[type] = text;
    input.setValue(text);
  },

  getControlTextClean: function(type) {
    // set id  and  text
    var value = '';
    if (type == 'county') {
      value = this['cityInput'].getValue().replace(/ County/g, '');
    } else {
      value = this[type + 'Input'].getValue();
    }
    return value.replace(/^([a-z\s]*)(.*)$/i, '$1').replace(/(^\s+)|(\s+$)/g, '');
  },

  getControlText: function(type) {
    // set id  and  text
    if (type == 'county') {
      var input = this['cityInput'];
    } else {
      var input = this[type + 'Input'];
    }
    return input.getValue();
  },

  _intellect: function(type) {
    this._activateNextSuggest(type);
  },

  _activateNextSuggest: function(type) {
    switch (type) {
      case 'country':
      //this._addActiveMarker_('city');
        this._focusControl('city');
        break;
      case 'state':
        if (this.id.city == 0 && this.text.city != '') {
          this._activateControl('city');
        } else if (this.id.county == 0 && this.text.county != '') {
            this._activateControl('city');
        } else
        if (this.id.city == null) {
          this._focusControl('city');
        }
        break;
      case 'city':
        if (this.id.state == null) {
          this._activateControl('state');
        }
        break;
      case 'county':
        if (this.id.state == null) {
          this._activateControl('state');
        }
        break;
      default:
    }
  },

  _removeActiveMarker_: function(type) {
    this[type + 'Container'].removeClassName('active');
  },

  _removeActiveMarkerAll_: function() {
    this._removeActiveMarker_('country');
    this._removeActiveMarker_('state');
    this._removeActiveMarker_('city');
  },

  _addActiveMarker_: function(type) {
    this._removeActiveMarkerAll_();
    this.currentActivemarker = type;
    this[type + 'Container'].addClassName('active');
  },

  _activateControl: function(type) {
    try {
      this[type + 'Input'].focus()
    } catch(e) {
    }
    try {
      this[type + 'AjaxInput'].activate()
    } catch(e) {
    }
  },

  _focusControl: function(type) {
    try {
      this[type + 'Input'].focus()
    } catch(e) {
    }
  },

  _blurControl: function(type) {
    try {
      this[type + 'Input'].blur()
    } catch(e) {
    }
  },

  onClear: function(event) {
    var element = Event.element(event);
    var type = element.readAttribute("valueType");
    this.clear(type);
},

  clear: function(type){
    switch (type) {
      case 'country':
        this.setControlValue('city', null, '');
        this.setControlValue('county', null, '');
        this.setControlValue('state', null, '');
        this.setControlValue('country', null, '');

        this.setControlText('city', '');
        this.setControlText('county', '');
        this.setControlText('state', '');
        this.setControlText('country', '');

        this.flagImg.src = '/media/flags/no_flag.png';

        break;
      case 'state':
        this.setControlValue('city', null, '');
        this.setControlValue('county', null, '');
        this.setControlValue('state', null, '');

        this.setControlText('city', '');
        this.setControlText('county', '');
        this.setControlText('state', '');
        /*
         */

      /*
      !!!
      this.city.element.parentNode.getElementsByTagName('A')[0].style.visibility = "hidden";
      this.state.element.parentNode.getElementsByTagName('A')[0].style.visibility = "hidden";
      */

        break;
      case 'city':
        this.setControlValue('city', null, '');
        this.setControlValue('county', null, '');

        this.setControlText('city', '');
        this.setControlText('county', '');

      /*
        this.setControlValue('state', null, '');
        this.setControlText('state', '');
      */
      /*
      !!!
      this.city.element.parentNode.getElementsByTagName('A')[0].style.visibility = "hidden";
      */

        break;
    }
    this._render();
    this._focusControl(type);
  },

  onChangeDumper: function(event) {
    d('dumper')
    this.hashOnChange++;
    var hash = this.hashOnChange;
    setTimeout(function(){
      if(hash == this.hashOnChange){
        this.onChange(event);
      }
    }.bind(this), 300);
  },

  onChange: function(event) {
    d('onCHANGE')
    if (this.id.country != null && this.getControlText('country') != this.recognizedText.country) {
      this.setControlValue('country', null, '');
      this.clear('state');
      this['countryContainer'].addClassName('undefined');
      d(':'+this.recognizedText.country+'!='+this.getControlText('country'))
    }
    if (this.id.state != null && this.getControlText('state') != this.recognizedText.state) {
      this.setControlValue('state', null, '');
      this.clear('city');
      this['stateContainer'].addClassName('undefined');
      d(':'+this.recognizedText.state+'!='+this.getControlText('state'))
    }
    if (this.id.city != null && this.getControlText('city') != this.recognizedText.city) {
      this.setControlValue('city', null, '');
      this.setControlValue('county', null, '');
      this['cityContainer'].addClassName('undefined');
      d(':'+this.recognizedText.city+'!='+this.getControlText('city'))
    }
    this._render();
    this._dispalyResult();
  },

  _idReady: function() {
    var result = false;
    if (this.countryInput && this.stateInput && this.cityInput) {
      result = true;
    }
    return result;
  }
});

placeControl2 = Class.create(Ajax.Autocompleter, {
  initialize: function(element, update, url, options) {
    this.baseInitialize(element, update, options);
    this.options.asynchronous  = true;
    this.options.onComplete  = this.onComplete.bind(this);
    this.options.defaultParams = this.options.parameters || null;
    this.url           = url;
    //this.options.afterUpdateElement = this.onSelectHook;
    this.options.updateElement = this.onSelectHook.bind(this);
    this.options.callback = this.onBeforeSendHook;
    this.options.onShow  = this.onShow.bind(this);
  },

  onShow: function(element, update){
    if (!update.style.position || update.style.position == 'absolute') {
      update.style.position = 'absolute';
      Position.clone(element, update, {
        setHeight: false,
        setWidth: false,
        offsetTop: element.offsetHeight
      });
    }
    Effect.Appear(update, {duration:0.15});
  },

  onComplete: function(request) {
    var text = request.responseText;
    var type = this.element.readAttribute("valueType");
    var objects = [];
    var response = text.evalJSON();
    var requestType = response.result.request;
    var _controller = this._controller;
    if (_controller.hash != response.result.hash){
      return;
    }
    var result = "<ul>";
    var self = this;
    try{
      //d(response.result.value.size());
      response.result.value.each(function(value,index) {
        var element = new Element('li');
        switch (requestType){
          case 'country':
            element.writeAttribute('valueId', value.ci);
            element.writeAttribute('valueName', value.cn);
            element.writeAttribute('ciso', value.ciso.toLowerCase());
            element.innerHTML = '<img src="/media/flags/'+value.ciso.toLowerCase()+'.png" />&nbsp;'+value.cn;
            element.writeAttribute('valueType', 'country');
            break;
          case 'state':
            element.writeAttribute('valueId', value.si?value.si:0);
            element.writeAttribute('valueName', value.sn?value.sn:'');
            element.innerHTML = value.sn?value.sn:'';
            if (value.cii && value.cin){
              element.writeAttribute('cii', value.cii);
              element.writeAttribute('cin', value.cin);
              //element.innerHTML = value.sn;
              //element.innerHTML = value.cin + ' ('+value.con + ' County)';
            }
            if (value.coi && value.con){
              element.writeAttribute('coi', value.coi);
              element.writeAttribute('con', value.con);
            }
            element.writeAttribute('valueType', 'state');
            break;
          case 'city':
            element.writeAttribute('valueId', value.cii?value.cii:null);
            element.writeAttribute('valueName', value.cin);
            element.innerHTML = value.cin;
            if (value.coi && value.con){
              element.writeAttribute('coi', value.coi);
              element.writeAttribute('con', value.con);
              element.innerHTML = value.cin + ' ('+value.con + ' County)';
            }
            element.writeAttribute('valueType', 'city');
            break;
          case 'cico':
            if (value.cin){
              element.writeAttribute('valueId', value.cii?value.cii:0);
              element.writeAttribute('valueName', value.cin);
              element.innerHTML = value.cin;
              if (value.coi && value.con){
                element.writeAttribute('coi', value.coi);
                element.writeAttribute('con', value.con);
                element.innerHTML = value.cin + ' ('+value.con + ' County)';
              }
              element.writeAttribute('valueType', 'city');
            }else{
              element.writeAttribute('valueId', value.coi?value.coi:0);
              element.writeAttribute('valueName', value.con);
              element.innerHTML = value.con + ' County';
              element.writeAttribute('valueType', 'county');
            }
            break;
        }

        element.writeAttribute('valueCaption', escape(element.innerHTML));
        //element.value = value.name;
        if (response.result.value.size() == 1){
          self._controller._blurControl(type);
          self.onSelectHook(element);
        }else{
          var div = new Element('div');
          div.appendChild(element);
          result += div.innerHTML;
        }
      });
    }catch(e){
      alert(e)
    }
    result += "</ul>";
    this.updateChoices(result);
  },

  onSelectHook: function(selected){
    //d(selected)
    var _controller = this._controller;
    //var _controller = input._controller;
    var text = selected.innerHTML;
    var id = selected.readAttribute("valueId");
    var value = selected.readAttribute("valueName");
    var type = selected.readAttribute("valueType");
    switch (type){
      case 'country':
        var ciso = selected.readAttribute("ciso");
        if (_controller.flagImg && ciso){
          _controller.flagImg.src = '/media/flags/'+ciso+'.png';
        }
        break;
      case 'state':
        var cii = selected.readAttribute("cii");
        var cin = selected.readAttribute("cin");
        if (cii && cin){
          _controller.setControlValue('city', cii, cin);
        }
        var coi = selected.readAttribute("coi");
        var con = selected.readAttribute("con");
        if (coi && con){
          _controller.setControlValue('county', coi, con);
        }
        /*
        var cii = selected.readAttribute("cii");
        if (cii){
          _controller.setControlValue('city', cii, _controller.text.city);
        }
        */
        break;
      case 'city':
        var coi = selected.readAttribute("coi");
        var con = selected.readAttribute("con");
        if (coi && con){
          _controller.setControlValue('county', coi, con);
        }
        //_controller.cityInput.setValue(text);
        break;
    }
    if (selected.readAttribute('valueType') == 'country'){
      _controller.setControlText(type, selected.readAttribute('valueName'));
    } else {
      _controller.setControlText(type, selected.innerHTML);
    }
    _controller.setControlValue(type, id, value);
    _controller._render();
    _controller._intellect(type);
    return;
  },

  onBeforeSendHook: function(input, query){
    //var request = "query="+query;
    var type = input.readAttribute("valueType");
    var _controller = input._controller;
    var result = {
      hash: String(Math.random()).substring(2,15),
      request: type,
      id: {
        country: (_controller.id.country==null?'':parseInt(_controller.id.country)),
        state: (_controller.id.state==null?'':parseInt(_controller.id.state)),
        county: (_controller.id.county==null?'':parseInt(_controller.id.county)),
        city: (_controller.id.city==null?'':parseInt(_controller.id.city)),
        place: ''
      },
      text: {
        /*
        country: (_controller.text.country),
        state: (_controller.text.state),
        city: (_controller.text.city),
        county: (_controller.text.county),
        place: ''
        */
      }
    };
    result.text.country = _controller.getControlTextClean('country');
    result.text.state = _controller.getControlTextClean('state');
    result.text.place = '';
    if (_controller.id.city == null && _controller.id.county == null){
      result.text.cico = _controller.getControlTextClean('city');
      result.text.city = '';
      result.text.county = '';
    } else if(_controller.id.city == 0 || _controller.id.city){
      result.text.city = _controller.getControlTextClean('city');
      result.text.county = '';
    } else if(_controller.id.county == 0 || _controller.id.county){
      result.text.city = '';
      result.text.county = _controller.getControlTextClean('county');
    }

    _controller.hash = result.hash;
    switch (type){
      case 'city':
        if (_controller.id.city == null && _controller.id.county == null){
          result.request = 'cico';
          result.text['cico'] = query.substring(1);
        }
      break;
      default:
        result.text[type] = query.substring(1);
        if(typeof _controller.complete.country[_controller.getControlText('country').toLowerCase()] == 'string'){
          var text = _controller.complete.country[_controller.getControlText('country').toLowerCase()];
          _controller.setControlText('country', text);
          result.text[type] = text;
        }
      break;
    }
    d(result);
    return "r="+Object.toJSON(result);
  },

  onChangeEvent: function(event){
  },

  onChangeHook: function(ebent){
  },
  
  fixIEOverlapping: function() {
    Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
    this.iefix.style.zIndex = 1;
    this.update.style.zIndex = 200;
    Element.show(this.iefix);
  },
  
  render: function() {
    if(this.entryCount > 10){
	      this.update.style.height = '300px';
    }else{
	      this.update.style.height = 'auto';
    };
    if(this.entryCount > 0) {
      for (var i = 0; i < this.entryCount; i++)
        this.index==i ? 
          Element.addClassName(this.getEntry(i),"selected") : 
          Element.removeClassName(this.getEntry(i),"selected");
      if(this.hasFocus) { 
        this.show();
        this.active = true;
      }
    } else {
      this.active = false;
      this.hide();
    }
  }
  
});
