"use strict";

var Promise = require("bluebird");

/**
 * @typedef {Object} google.maps.Marker
 */

/* exported logger */

// noinspection JSUnusedLocalSymbols
var logger = require('./logger');

// noinspection JSUnusedGlobalSymbols
var google = {
  maps: {
    event: {
      _data: [],
      addListener: function (object, type, fun) {
        google.maps.event._data.push({
          object: object,
          type: type,
          fun: fun
        });
      },
      addDomListener: function (object, type, fun) {
        object.addEventListener(type, fun);
      },
      trigger: function (object, type, param) {
        var promises = [];
        for (var i = 0; i < google.maps.event._data.length; i++) {
          var e = google.maps.event._data[i];
          if (e.object === object && e.type === type) {
            promises.push(e.fun(param));
          }
        }
        return Promise.all(promises);
      }
    },
    drawing: {
      DrawingManager: function (options) {
        this.options = options;
        if (this.options === undefined) {
          this.options = {};
        }
        this.setMap = function (map) {
          this.options.map = map;
        };
        // noinspection JSUnusedGlobalSymbols
        this.setDrawingMode = function (mode) {
          this.options.drawingMode = mode;
        };
        this.getDrawingMode = function () {
          return this.options.drawingMode;
        };
      },
      OverlayType: {
        MARKER: "MARKER"
      }
    },

    ControlPosition: {
      TOP_LEFT: "TOP_LEFT",
      LEFT_BOTTOM: "LEFT_BOTTOM",
      RIGHT_BOTTOM: "RIGHT_BOTTOM",
      RIGHT_TOP: "RIGHT_TOP"
    },
    /**
     * @typedef {Object} google.maps.LatLng
     * @property {function():number} lat
     * @property {function():number} lng
     */

    /**
     *
     * @param lat
     * @param lng
     * @returns {google.maps.LatLng}
     * @constructor
     */
    LatLng: function (lat, lng) {
      this.latitude = parseFloat(lat);
      this.longitude = parseFloat(lng);

      this.lat = function () {
        return this.latitude;
      };
      this.lng = function () {
        return this.longitude;
      };
      return this;
    },
    LatLngBounds: function (ne, sw) {
      var data = {
        ne: ne,
        sw: sw
      };
      // noinspection JSUnusedGlobalSymbols
      return {
        getSouthWest: function () {
          return data.sw;
        },
        getNorthEast: function () {
          return data.ne;
        },
        getCenter: function () {
          return new google.maps.LatLng((data.ne.lat() + data.sw.lat()) / 2, (data.ne.lng() + data.sw.lng()) / 2);
        },
        isEmpty: function () {
          return data.ne === data.sw || (data.ne.lat() === data.sw.lat() && data.ne.lng() === data.sw.lng());
        },
        extend: function (arg) {
          if (data.sw === undefined) {
            data.sw = new google.maps.LatLng(arg.lat(), arg.lng());
          } else {
            if (arg.lng() < data.sw.lng()) {
              data.sw.longitude = arg.lng();
            }
            if (arg.lat() < data.sw.lat()) {
              data.sw.latitude = arg.lat();
            }
          }
          if (data.ne === undefined) {
            data.ne = new google.maps.LatLng(arg.lat(), arg.lng());
          } else {
            if (arg.lng() > data.ne.lng()) {
              data.ne.longitude = arg.lng();
            }

            if (arg.lat() > data.ne.lat()) {
              data.ne.latitude = arg.lat();
            }
          }
        }

      };
    },
    OverlayView: function () {
      return {};
    },
    ImageMapType: function () {
      return {};
    },
    InfoWindow: function (options) {
      this.options = options;
      if (this.options === undefined) {
        this.options = {};
      }
      this.getMap = function () {
        return this.options.map;
      };
      this.setMap = function (map) {
        this.options.map = map;
      };
      this.open = function (map) {
        this.setMap(map);
      };
      this.setContent = function () {
      };
    },
    /**
     *
     * @param options
     * @returns {google.maps.Marker}
     * @constructor
     */
    Marker: function (options) {
      this.options = options;
      this.position = options.position;
      this.getMap = function () {
        return this.options.map;
      };
      this.setMap = function (map) {
        this.options.map = map;
      };
      this.setIcon = function (icon) {
        this.options.icon = icon;
      };
    },

    MarkerImage: function () {
      return {};
    },
    /**
     *
     * @param div
     * @param options
     * @returns {{controls: {TOP_LEFT: Array, LEFT_BOTTOM: Array, RIGHT_BOTTOM: Array, RIGHT_TOP: Array}, getDiv: function(): *, mapTypes: {set: mapTypes.set}, getMapTypeId: function(): *, setMapTypeId: setMapTypeId, setOptions: setOptions, getZoom: function(): *, setZoom: function(*=): *, getCenter: function(): (google.maps.LatLng|google.maps.Point|*), panBy: panBy, setCenter: function(*=): *, getBounds: function(): (google.maps.LatLngBounds|*), setBounds: setBounds, fitBounds: fitBounds}}
     * @constructor
     */
    Map: function (div, options) {
      var data = {};
      if (options !== undefined) {
        data = options;
      }
      if (data.center === undefined) {
        data.center = new google.maps.LatLng(83.42558775689403, -135);
      }
      data.div = div;
      if (data.bounds === undefined) {
        data.bounds = new google.maps.LatLngBounds(new google.maps.LatLng(10, 10), new google.maps.LatLng(12, 12));
      }

      // noinspection JSUnusedGlobalSymbols
      return {
        controls: {
          "TOP_LEFT": [],
          "LEFT_BOTTOM": [],
          "RIGHT_BOTTOM": [],
          "RIGHT_TOP": []
        },
        getDiv: function () {
          return data.div;
        },
        mapTypes: {
          set: function () {
          }
        },
        getMapTypeId: function () {
          return data.mapTypeId;
        },
        setMapTypeId: function (id) {
          data.mapTypeId = id;
          google.maps.event.trigger(this, "maptypeid_changed", id);
        },
        setOptions: function () {
        },
        getZoom: function () {
          return data.zoom;
        },
        setZoom: function (zoom) {
          data.zoom = zoom;
          return google.maps.event.trigger(this, "zoom_changed", zoom);
        },
        getCenter: function () {
          return data.center;
        },
        panBy: function (x, y) {
          if (data.center !== undefined) {
            data.center.x += x;
            data.center.y += y;
          } else {
            data.center = new google.maps.Point(x, y);
          }
        },
        setCenter: function (center) {
          data.center = center;
          return google.maps.event.trigger(this, "center_changed", center);
        },
        getBounds: function () {
          return data.bounds;
        },
        setBounds: function (bounds) {
          data.bounds = bounds;
        },
        fitBounds: function (bounds) {
          this.setBounds(bounds);
          this.setCenter(bounds.getCenter());
        }
      };
    },
    MVCArray: function (data) {
      if (data !== undefined) {
        this.data = data;
      } else {
        this.data = [];
      }
      this.getLength = function () {
        return this.data.length;
      };
      this.length = this.data.length;
      this.getAt = function (index) {
        return this.data[index];
      };
    },
    Point: function (x, y) {
      this.x = x;
      this.y = y;
    },
    Polyline: function (options) {
      this.options = options;
      if (this.options === undefined) {
        this.options = {};
      }
      this.setOptions = function () {
      };
      this.getPath = function () {
        return new google.maps.MVCArray();
      };
      this.getMap = function () {
        return this.options.map;
      };
      this.setMap = function (map) {
        this.options.map = map;
      };
    },
    /**
     * @typedef {Object} google.maps.Polygon
     * @property {function():google.maps.MVCArray} getPath
     * @property {function():google.maps.Map} getMap
     */

    /**
     *
     * @param options
     * @returns {google.maps.Polygon}
     * @constructor
     */
    Polygon: function (options) {
      this.options = options;
      if (this.options.paths !== undefined) {
        this.options.path = new google.maps.MVCArray(this.options.paths);
      }
      if (this.options.path === undefined) {
        this.options.path = new google.maps.MVCArray();
      }
      this.getPath = function () {
        return this.options.path;
      };
      this.getMap = function () {
        return this.options.map;
      };
      this.setMap = function (map) {
        this.options.map = map;
      };
    },
    Rectangle: function (options) {
      this.options = options;
      if (this.options === undefined) {
        this.options = {};
      }
      this.getMap = function () {
        return this.options.map;
      };
      this.setMap = function (map) {
        this.options.map = map;
      };
      this.setOptions = function (options) {
        for (var key in options) {
          if (options.hasOwnProperty(key)) {
            this.options[key] = options[key];
          }
        }
      };
      this.getBounds = function () {
        return this.options.bounds;
      };
      this.setBounds = function (bounds) {
        this.options.bounds = bounds;
      };
    },
    Size: function () {
      return {};
    },
    ZoomControlStyle: {
      LARGE: "LARGE"
    }
  }
};

google.maps.Map.prototype.fitBounds = function () {
};

module.exports = google;