(function() {
  var characters  = "0123456789 AaÀÁÂÃàáâãBbCcÇçĆćČčDdÐðEeÈÉÊËèéêëFfGgHhIiÌÍÎÏìíîïJjKkLlŁłMmNnÑñŃńOoÒÓÔòóôPpQqRrŘřSsŚśšTtUuÙÚÛùúûVvWwXxYyÜÝüýZzÅåÄÆäæÖØöø!@#$%^&*()+-/";
  var seNormalize = "0123456789 aaaaaaaaaabbccccccccddddeeeeeeeeeeffgghhiiiiiiiiiijjkkllllmmnnnnnnooooooooppqqrrrrsssssttuuuuuuuuvvwwxxyyyyyyzzååääääöööö!@#$%^&*()+-/"
  var sortable    = "0123456789 AAAAAAAAAABBCCCCCCCCDDDDEEEEEEEEEEFFGGHHIIIIIIIIIIJJKKLLLLMMNNNNNNOOOOOOOOPPQQRRRRSSSSSTTUUUUUUUUVVWWXXYYYYYYZZaabbbbcccc             ";

  function replaceCharacters(string, fromChars, toChars) {
    var t, r = [];
    for (var ix = 0; ix < string.length; ++ix) {
      t = fromChars.indexOf(string.charAt(ix));
      if (t >= 0) {
        r.push(toChars.charAt(t));
      }
    }
    return r.join('');
  }

  function longestCommonSubstring(string1, string2) {
    // init max value
    var longestCommonSubstring = 0;

    // init 2D array with 0
    var table = Array(string1.length);
    for(a = 0; a <= string1.length; a++){
      table[a] = Array(string2.length);
      for(b = 0; b <= string2.length; b++){
        table[a][b] = 0;
      }
    }
    // fill table
    for(var i = 0; i < string1.length; i++){
      for(var j = 0; j < string2.length; j++){
        if(string1[i]==string2[j]){
          if(table[i][j] == 0){
            table[i+1][j+1] = 1;
          } else {
            table[i+1][j+1] = table[i][j] + 1;
          }
          if(table[i+1][j+1] > longestCommonSubstring){
            longestCommonSubstring = table[i+1][j+1];
          }
        } else {
          table[i+1][j+1] = 0;
        }
      }
    }

    return longestCommonSubstring;
  }

  function prefixLength(string1, string2) {
    for (var ix = 0; ix < string1.length; ++ix) {
      if (string1[ix] != string2[ix]) {
        return ix;
      }
    }
    return ix;
  }

  String.prototype.seNormalize = function() {
    return replaceCharacters(this, characters, seNormalize);
  };
  String.prototype.sortable = function() {
    return replaceCharacters(this.replace('&amp;', '&'), characters, sortable);
  };

  Array.prototype.autocompleteFilter = function(string) {
    if (string == null || string == '') {
      return [];
    }

    var maxResults = 9;

    string = string.seNormalize();
    var parts = _.map(string.split(' '), function(p) { return p.trim(); });

    var results = _.filter(this, function(s) {
      var n = s.seNormalize();

      if (n.indexOf(parts[0]) >= 0) {
        var match = true;
        for (var ix = 1; ix < parts.length; ++ix) {
          if (n.indexOf(parts[ix]) < 0) {
            match = false;
          }
        }

        return match;
      }
    });

    if (results.length < 1000) {
      results = _.sortBy(results, function(r) {
        return 0 - longestCommonSubstring(string, r.search) - 0.01 * prefixLength(r.seNormalize(), string)
      });
    }

    var count = results.length;
    results = results.slice(0, maxResults);
    results.result_count = count;

    return results;
  }
})();

var UhrApplication = React.createClass({
  getInitialState: function() {
    autocomplete = new Promise(function(resolve, reject) {
      $.ajax({
        url: '/api/autocomplete',
        success: function(data) {
          resolve(data);
        }.bind(this),
        error: function(xhr, status, err) {
          console.error("/api", status, err.toString());
          reject(err);
        }.bind(this)
      });
    });
    window.autocomplete = autocomplete;

    String.prototype.autocomplete = function() { return []; }
    autocomplete.then(function(data) {
      String.prototype.autocomplete = function(field) {
        return data[field].autocompleteFilter(this);
      }
    })

    return { recordId: null, view: 'list', search: {}, offset: 0, loggedIn: false, autocomplete: autocomplete }
  },
  onNavigate: function(to) {
    console.debug("onNavigate()", to);
    this.setState(to);
    this.refs.nav.setState({ recordId: to.recordId });
  },
  onRecordClicked: function(record) {
    this.onNavigate({
      view: 'show',
      recordId: record.Id
    });
  },
  render: function() {
    return (
      <div id="lv1">
        <Navbar onNavigate={this.onNavigate} ref="nav" />
        <div className="page-content">
          {this.renderView()}
        </div>
      </div>
    );
  },
  renderView: function() {
    if (!this.state.loggedIn) {
      return (
        <LoginView onLogin={this.onLogin} />
      );
    }

    if (this.state.view == 'list') {
      return (
        <ListView onRecordClicked={this.onRecordClicked} title="Alla poster" />
      );
    } else if (this.state.view == 'show') {
      return (
        <RecordView id={this.state.recordId} showClone={this.showClone} onSaved={this.onNavigate.bind(this, { recordId: null, view: 'list' })} />
      );
    } else if (this.state.view == 'new') {
      return (
        <RecordView id="new" record={this.state.clone} onSaved={this.onNavigate.bind(this, { recordId: null, view: 'list' })} />
      );
    } else if (this.state.view == 'search') {
      return (
        <div>
          <h1>Sök UHR-poster</h1>
          <RecordForm record={this.state.search} text="false" emptyOptions="true" onUpdate={this.onSearchUpdated} />
          <button onClick={this.onSearch}>Sök</button>
          <button onClick={this.onClearSearch} style={{ marginLeft: '20px' }}>Rensa</button>
        </div>
      );
    } else if (this.state.view == 'results') {
      return (
        <ListView onRecordClicked={this.onRecordClicked} search={this.state.search} title="Sökresultat" />
      )
    }
  },
  onSearchUpdated: function(search) {
    this.setState({ search: search });
  },
  onSearch: function() {
    this.setState({ view: 'results' });
  },
  onClearSearch: function() {
    this.setState({ search: { Brand: '', Cartype: '' } });
  },
  onLogin: function(token) {
    $.ajaxSetup({ headers: { 'X-UHR-Auth-Token': token }});
    this.setState({ loggedIn: true });
  },
  showClone: function(clone) {
    this.setState({ view: 'new', recordId: null, clone: clone })
  }
});
