var Service = function () {};
Service.prototype = {
  initialize: function (map) {
    var self = this;
    this.map = map;
    this.page = 1;
    this.total_num = 0;
    this.perPage = 20;
    this.$status = $('#service_status');
    this.$active = $('#' + this.name + '_active');
    this.markers = [];

    $('a.page', this.$c).die().live('click', function (e) { e.preventDefault();
      self.fetch(($(this).hasClass('next')) ? self.page+1: self.page-1);
    });
  },
  isActivated: function () {
    return this.$active.is(':checked');
  },
  linkCallback: function (e, preventGEvent) { e.preventDefault();
    var
      $t = $(this),
      id = $t.attr('rel'),
      markers = e.data.markers,
      marker = markers[id];
    if (typeof marker == 'undefined') return false;

    var $target = $t.addClass('active').parents('ul:first');
    if (!$target.is(':visible')) {
      $('#items ul').hide();
      $target.show();
      $('#navi_header li').removeClass('active');
      $('#' + $target.attr('id') + '_navi').addClass('active');
    }

    if (preventGEvent !== true) {
      GEvent.trigger(marker, 'click');
    }
  },
  clearMarkers: function () {
    for (var i in this.markers) {
      this.map.removeOverlay(this.markers[i]);
    }
    this.markers = [];
    return this;
  },
  paginateHtml: function () {
    var
      start = (this.page*this.perPage)-this.perPage+1,
      end = (this.total_num > (start+this.perPage-1)) ? start+this.perPage-1: this.total_num,
      h = '<li class="align_center">';
    if (this.page != 1)
      h += '<a href="#" class="page prev">&laquo; 前へ</a>';
    h += ' &nbsp; ' + start + ' - ' + end + ' / ' + this.total_num + ' &nbsp; ';
    if (end < this.total_num) {
      h += '<a href="#" class="page next">次へ &raquo;</a>';
    }
    h += '</li>';
    return h;
  }
};


var HotPepper = function (map) {
  this.name = 'hotpepper';
  this.$c = $('#hotpepper');
  this.initialize(map);
};
HotPepper.prototype = new Service();

HotPepper.prototype.fetch = function (page, lat, lng) {
  if (!this.isActivated()) return false;
  this.$c.html('<li style="padding: 12px 0;">ホットペッパーを読み込み中...</li>');
  var
    self = this,
    map = this.map,
    page = page || self.page,
    start = (self.page*self.perPage)-self.perPage+1,
    opts = {
      key: '5a138ce8d1eb8116',
      lat: lat || self.lat,
      lng: lng || self.lng,
      range: 2,
      count: self.perPage,
      start: (page*self.perPage)-self.perPage+1,
      format: 'jsonp'
    };
  this.clearMarkers();
  $.getJSON('http://webservice.recruit.co.jp/hotpepper/gourmet/v1/?callback=?', opts, function (o) {
    if (!o.results || !o.results.shop) return false;
    self.total_num = o.results.results_available;
    self.page = page;
    self.lat = lat || self.lat;
    self.lng = lng || self.lng;
    var h = '', markers = {};
    $(o.results.shop).each(function (i, v) {
      var marker = map.infoMarker(self.name, v.id, new GLatLng(v.lat, v.lng),
                                  '/images/party.png', self.build(v));
      map.addOverlay(marker);
      h +=
        '<li>' +
        ' <div class="name"><a href="#" id="' + v.id + '" title="' + v.name_kana + '" rel="' + v.id + '" class="link">' + v.name + ' &raquo;</a></div>' +
        ' <div class="info">' +
        '  <div>' + v.food.name + '</div>' + 
        '  <div>' + v.access + '</div>' +
        '  <div class="desc">' + v['catch'] + '</div>' +
        ' </div>' +
        '</li>';
      markers[v.id] = marker;
      self.markers.push(marker);
    });
    h += self.paginateHtml();
    self.$c.html(h).find('a.link').bind('click', {markers: markers}, self.linkCallback);
  });
  return this;
};
HotPepper.prototype.build = function (v) {
  var html =
    '<div class="right" style="margin:0 0 7px 7px;">' +
    ' <img src="' + v.photo.pc.s + '" alt="" width="79" height="79" /><br />' +
    '</div>' +
    '<div class="medium bold">' + v.name + '</div>' + 
    '<div class="external"><a href="' + v.urls.pc + '" target="_blank" id="' + v.id + '_link" class="external_link">このお店のページを開く &raquo;</a></div>' +
    '<div>' + v.food.name + '</div>' + 
    '<p>' + v['catch'] + '</p>' +
    '<div class="gray">' + v.address + '</div>' +
    '<span>' + v.budget.average + '</span><br />' +
    '<span>[営業時間] ' + v.open + '</span>' +
    '<p class="clear_both align_center">' +
    '<a href="http://webservice.recruit.co.jp/"><img src="http://webservice.recruit.co.jp/banner/hotpepper-s.gif" alt="ホットペッパー Webサービス" width="135" height="17" class="valign_middle" title="ホットペッパー Webサービス" /></a> &nbsp; ' +
    '<span class="x-small">【画像提供：ホットペッパー　FooMoo】</span>' +
    '</p>';
  return html;
};


var Tabelog = function (map) {
  this.name = 'tabelog';
  this.$c = $('#tabelog');
  this.initialize(map);
};
Tabelog.prototype = new Service();

Tabelog.prototype.fetch = function (page, lat, lng) {
  if (!this.isActivated()) return false;
  this.$c.html('<li style="padding: 12px 0;">食べログを読み込み中...</li>');
  this.clearMarkers();
  var self = this, map = this.map, markers = {}, h = '';
  $.ajax({
    url: '/api/tabelog',
    data: {
      lat: lat || self.lat, lng: lng || self.lng,
      page: page || self.page, per_page: self.perPage
    },
    dataType: 'json',
    success: function (o) {
      if (!o || !o.restraunts) return false;
      self.total_num  = o.total_num;
      self.page = page || self.page;
      self.lat = lat || self.lat;
      self.lng = lng || self.lng;
      $(o.restraunts).each(function (i, v) {
        var marker = map.infoMarker(self.name, v.rcd, new GLatLng(v.latitude, v.longitude),
                                    '/images/pens.png', self.build(v));
        markers[v.rcd] = marker;
        map.addOverlay(marker);
        self.markers.push(marker);
        h +=
          '<li>' +
          ' <div class="name"><a href="#" id="' + v.rcd + '" class="link" rel="' + v.rcd +'">' + v.name + ' &raquo;</a></div>' +
          ' <div class="info">' +
          '  <div>' + v.category + '</div>' + 
          '  総合: <span class="score">' + v.total_score + '</span>' +
          ' </div>' +
          '</li>';
      });
      h += self.paginateHtml();
      self.$c.html(h).find('a.link').bind('click', {markers: markers}, self.linkCallback);
    },
    error: function () {
      self.$c.html('<p style="font-style:italic;">[食べログ] エラーが発生しました</p>');
    }
  });
  return this;
};
Tabelog.prototype.build = function (v) {
  var html =
    '<div class="medium bold">' +v.name + '</div>' +
    '<div class="external"><a href="' + v.pc_url + '" target="_blank" id="' + v.rcd + '_link" class="external_link">このお店のページを開く &raquo;</a></div>' +
    '<div>' + v.category + '</div>' +
    '<div class="gray">' + v.address + '</div>' +
    '<div class="green">' + v.tel + '</div>' +
    '<div>' + v.business_hours + '</div>' +
    '<div>' + v.lunch_price + '(ランチ) ' +  v.dinner_price + '(ディナー)</div>' +
    '<p style="width:400px;">' +
    ' 総合: <span class="medium bold">' + v.total_score + '</span><br />' +
    ' 味: <span class="bold">' + v.taste_score + '</span>' +
    ' サービス: <span class="bold">' + v.service_score + '</span>' +
    ' ムード: <span class="bold">' + v.mood_score + '</span>' +
    '</p>' +
    '<div class="align_center"><a href="http://tabelog.com"><img src="http://image.tabelog.com/images/banner/tabelog_api_135x17.gif" alt="食べログAPI" title="食べログAPI" border="0" /></a></div>';
  return html;
};


var Gnavi = function (map) {
  this.name = 'gnavi';
  this.$c = $('#gnavi');
  this.initialize(map);
};
Gnavi.prototype = new Service();

Gnavi.prototype.fetch = function (page, lat, lng) {
  if (!this.isActivated()) return false;
  this.$c.html('<li style="padding: 12px 0;">ぐるなびを読み込み中...</li>');
  this.clearMarkers();
  var self = this, map = this.map, markers = {}, h = '';
  $.ajax({
    url: '/api/gnavi',
    data: {
      lat: lat || self.lat, lng: lng || self.lng,
      page: page || self.page, per_page: self.perPage
    },
    dataType: 'json',
    timeout: 10000,
    success: function (o) {
      if (!o || !o.restraunts) return false;
      self.total_num  = o.total_num;
      self.page = page || self.page;
      self.lat = lat || self.lat;
      self.lng = lng || self.lng;
      $(o.restraunts).each(function (i, v) {
        var marker = map.infoMarker(self.name, v.id, new GLatLng(v.latitude, v.longitude),
                                    '/images/gourmet.png', self.build(v));
        markers[v.id] = marker;
        map.addOverlay(marker);
        self.markers.push(marker);
        h +=
          '<li>' +
          ' <div class="name"><a href="#" id="' + v.id + '" class="link" rel="' + v.id +'">' + v.name + ' &raquo;</a></div>' +
          ' <div class="info">' +
          '  <div>' + v.pr_short + '</div>' + 
          ' </div>' +
          '</li>';
      });
      h += self.paginateHtml();
      self.$c.html(h).find('a.link').bind('click', {markers: markers}, self.linkCallback);
    },
    error: function () {
      self.$c.html('<p style="font-style:italic;">[ぐるなび] エラーが発生しました</p>');
    }
  });
  return this;
};

Gnavi.prototype.build = function (v) {
  var html =
    '<div class="right" style="margin:0 0 7px 7px;">' +
    ' <img src="' + v.photo + '" alt="" width="79" height="79" /><br />' +
    ' <div class="align_right">提供：ぐるなび</div>' +
    '</div>' +
    '<div class="bold medium">' + v.name + '</div>' +
    '<div class="external"><a href="' + v.url + '" target="_blank" id="' + v.id + '_link" class="external_link">このお店のページを開く &raquo;</a></div>' +
    '<div class="gray">' + v.address + '</div>' +
    '<div class="green">' + v.tel + '</div>' +
    '<div>￥ ' + v.budget + ' 〜</div>' +
    '<div>[営業時間] ' + v.opentime + '</div>' +
    '<p style="width:400px;">' + v.pr_long + '</p>' +
    '<div class="align_center">' +
    '<a href="http://www.gnavi.co.jp/"><img src="http://apicache.gnavi.co.jp/image/rest/b/api_155_20.gif" width="155" height="20" class="valign_middle" alt="グルメ情報検索サイト　ぐるなび" /></a> &nbsp;' +
    '</div>';
  return html;
};


var Ylocal = function (map) {
  this.name = 'ylocal';
  this.$c = $('#ylocal');
  this.initialize(map);
};
Ylocal.prototype = new Service();

Ylocal.prototype.fetch = function (page, lat, lng) {
  if (!this.isActivated()) return false;
  this.$c.html('<li style="padding: 12px 0;">付近の建物を読み込み中...</li>');
  this.clearMarkers();
  var self = this, map = this.map, markers = {}, h = '', page = page || self.page;

  var opts = {
    appid: 'zlxYTiixg65_oTDaLuW8W7PExjg4TXvk45_hPTRalPwgCJGzp3QPMdHTT4Q6x2Y-',
    lat: lat || self.lat, lon: lng || self.lng,
    b: ((page*self.perPage)-self.perPage+1),
    datum: 'wgs', dist: 1.0, n: self.perPage, category: 'courpon', o: 'json'
  };
  $.getJSON('http://map.yahooapis.jp/LocalSearchService/V1/LocalSearch?callback=?', opts, function (o) {
    if (!o || !o.Item) return false;
    self.total_num  = o.Count;
    self.page = page || self.page;
    self.lat = lat || self.lat;
    self.lng = lng || self.lng;
    $(o.Item).each(function (i, v) {
      v.id = 'y_' + i;
      var marker = map.infoMarker(self.name, v.id, new GLatLng(v.DatumWgs84.Lat, v.DatumWgs84.Lon),
                                  '/images/gourmet.png', self.build(v));
      markers[v.id] = marker;
      map.addOverlay(marker);
      self.markers.push(marker);
      h +=
        '<li>' +
        ' <div class="name"><a href="#" id="' + v.id + '" class="link" rel="' + v.id +'">' + v.Title + '</a></div>' +
        ' <div class="info">';
      if (o.Url)
        h += '<div class="align_right"><a href="' + v.Url + '" target="_blank" class="x-small">詳細を見る &raquo;</a></div>';
      h +=
        ' </div>' +
        '</li>';
    });
    h += self.paginateHtml();
    self.$c.html(h).find('a.link').bind('click', {markers: markers}, self.linkCallback);
});
  return this;
};

Ylocal.prototype.build = function (v) {
  var html = '<div>';
  if (v.Url)
    html = '<a href="' + v.Url + '" class="bold medium" target="_blank">' + v.Title + '</a>';
  else
    html = '<span>' + v.Title + '</span>';
    '<div class="gray">' + v.Address + '</div>' +
    '</div>';
  return html;
};

GMap2.prototype.initServices = function () {
  this.services = {
    hotpepper: new HotPepper(this),
    tabelog: new Tabelog(this),
    gnavi: new Gnavi(this)
    //ylocal: new Ylocal(this)
  };
  return this;
};

GMap2.prototype.initService = function (name) {
  switch (name) {
    case 'hotpepper': return new HotPepper(this); break;
    case 'tabelog': return new Tabelog(this); break;
    case 'gnavi': return new Gnavi(this); break;
    //case 'ylocal': return new Ylocal(this); break;
    default: null;
  }
};

GMap2.prototype.drawMap = function (lat, lng) {
  this.initServices();
  this.services.hotpepper.fetch(1, lat, lng);
  this.services.tabelog.fetch(1, lat, lng);
  this.services.gnavi.fetch(1, lat, lng);
  //this.services.ylocal.fetch(1, lat, lng);
  return this;
};

GMap2.prototype.infoMarker = function (name, id, point, icon_image, content, callback, opts) {
  var map = this, opts = opts || {};
  opts.icon = new GIcon(G_DEFAULT_ICON);
  opts.icon.image = icon_image;
  opts.icon.iconSize = new GSize(27, 27);
  opts.icon.shadowSize = new GSize(0, 0);
  var marker = new GMarker(point, opts);
  if (!$.isFunction(callback)) {
    callback = function() {
      marker.openInfoWindowHtml(content, {maxWidth: 500});
      $('#' + id).trigger('click', [true]);
      map.onMarkerSelected(name, id);
    }
  }
  GEvent.addListener(marker, 'click', callback);
  return marker;
};

GMap2.prototype.onMarkerSelected = function (name, id) {
  $('#' + id + '_link').die().live('click', function (e) {
//    console.info('clicked!! name: %s, id: %s', name, id);
    $.ajax({
      url: '/external/',
      data: {id: id, name: name},
      dataType: 'json',
      success: function (o) {}
    });
  });
};

GMap2.prototype.geoSearch = function () {
  this.$status.html('検索中...');
  var map = this;
  this.geocode.getLatLng(this.$query.val(), function(LatLng) {
    if (LatLng != null) {
      map.setCenter(LatLng, 17);
      map.drawMap(LatLng.lat(), LatLng.lng());
      GEvent.trigger(map, 'dragend');
    } else {
      setTimeout(function () { map.$status.html(''); }, 1200);
    }
    map.$status.empty();
  });
};




var initMap = function (latlng, callback) {
  var
    $w = $(window), $h = $('#header'), $c = $('#container'),
    $map = $('#map'), $ss = $('#service_status'), $items = $('#items'),
    onWindowResize = function () {
      var h = $w.height()-$h.outerHeight(true);
      $map.height(h);
      $items.height(h-$ss.height()-135);
    },
    opts = {lat: latlng.lat, lng: latlng.lng, zoom: 17};
  onWindowResize();
  $w.resize(onWindowResize);

  var map = new GMap2($map[0]);
  map.setCenter(new GLatLng(opts.lat, opts.lng), opts.zoom);
  map.addControl(new GLargeMapControl());
  map.addControl(new GMapTypeControl());

  map.centerMarker = null;
  map.geocode = new GClientGeocoder();
  map.$status = $('#status');
  map.$query = $('#query');

  $('#navi_header a.header_link').click(function (e) { e.preventDefault();
    var $t = $(this), name = $t.attr('href').substr(1), $target = $('#' + name);
    if ($target.is(':visible')) return false;
    $items.find('ul').hide();
    $target.show();
    $('#navi_header li').removeClass('active');
    $t.parent('li').addClass('active');
    $('li', $ss).hide().removeClass('active');
    $('#' + name + '_status').show().addClass('active');
  });

  GEvent.addListener(map, 'dragend', function() {
    if (this.centerMarker != null) this.removeOverlay(this.centerMarker);
    var center = this.getCenter();
    map.centerMarker = map.infoMarker(null, '__c__', center, '/images/down.png', null, function () {
      map.clearOverlays();
      var p = this.getPoint();
      map.drawMap(p.lat(), p.lng());
    }, {draggable: true});
    map.addOverlay(map.centerMarker);
  });

  GEvent.trigger(map, 'dragend');

  if ($.isFunction (callback)) {
    callback.apply(map, [opts, $items]);
  }

  if (!location.hostname.match(/^localhost/)) {
    var adsManagerOptions = {
      style: 'adunit',
      minZoomLevel: 1,
      channel: '7891020452'
    };
    var adsManager = new GAdsManager(map, 'ca-pub-8016552340374363', adsManagerOptions);
    adsManager.enable();
  }

  $('#geo_search').submit(function () {
    map.geoSearch();
    return false;
  });
};

