<commit_before>//
//  Marker.swift
//  ios-sdk
//
//  Created by <NAME> on 3/22/17.
//  Copyright © 2017 Mapzen. All rights reserved.
//

import Foundation
import TangramMap

@objc public enum MarkerType : Int {
  case currentLocation, searchPin, routeLine
}

@objc(MZGenericMarker)
public protocol GenericMarker {
  var tgMarker: TGMarker { get }
  var point: TGGeoPoint { get set }
  var polyline: TGGeoPolyline? { get set }
  var polygon: TGGeoPolygon? { get set }
  var icon: UIImage? { get set }
  var visible: Bool { get set }
  var drawOrder: Int { get set }
  var size: CGSize { get set }
  var backgroundColor: UIColor { get set }
  var interactive: Bool { get set }
  var active: Bool { get set }

  func setPointEased(_ coordinates: TGGeoPoint, seconds: Float, easeType ease: TGEaseType) -> Bool

  static func initWithMarkerType(_ markerType: MarkerType) -> GenericMarker
  init()
  init(size s: CGSize)
}

public class Marker : NSObject, GenericMarker {

  private static let kPointStyle = "points"
  private static let kLineStyle = "lines"
  private static let kPolygonStyle = "polygons"
  private static let kDefaultBackgroundColor = UIColor.white
  private static let kDefaultInteractive = true
  private static let kDefaultSize = CGSize.zero
  private static let kDefaultActive = true

  var styleType = Marker.kPointStyle
  var markerType: MarkerType?

  // all marker types have an associated styling path
  private let typeToStylingPath = [MarkerType.currentLocation : "layers.mz_current_location_gem.draw.ux-location-gem-overlay",
                                   MarkerType.searchPin : "layers.mz_search_result.draw.ux-icons-overlay",
                                   MarkerType.routeLine : "layers.mz_route_line.draw.ux-route-line-overlay"]
  //currently only search results have an inactive state
  private let typeToInactiveStylingPath = [MarkerType.searchPin : "layers.mz_search_result.inactive.draw.ux-icons-overlay"]

  private let internalTgMarker: TGMarker
  private var userUpdatedSize = false

  public var tgMarker: TGMarker {
    get {
      return internalTgMarker
    }
  }

  public var point: TGGeoPoint {
    set {
      tgMarker.point = newValue
      styleType = Marker.kPointStyle
      updateStyleString()
    }
    get {
      return tgMarker.point
    }
  }

  public var polyline: TGGeoPolyline? {
    set {
      guard let l  = newValue else { return }
      tgMarker.polyline = l
      styleType = Marker.kLineStyle
      updateStyleString()
    }
    get {
      return tgMarker.polyline
    }
  }

  public var polygon: TGGeoPolygon? {
    set {
      guard let p = newValue else { return }
      tgMarker.polygon = p
      styleType = Marker.kPolygonStyle
      updateStyleString()
    }
    get {
      return tgMarker.polygon
    }
  }
  public var icon: UIImage? {
    set {
      guard let i = newValue else { return }
      tgMarker.icon = i
      size = i.size
      styleType = Marker.kPointStyle
      updateStyleString()
    }
    get {
      return tgMarker.icon
    }
  }

  public var visible: Bool {
    set {
      tgMarker.visible = newValue
    }
    get {
      return tgMarker.visible
    }
  }

  public var drawOrder: Int {
    set {
      tgMarker.drawOrder = newValue
    }
    get {
      return tgMarker.drawOrder
    }
  }

  public var size: CGSize {
    didSet {
      userUpdatedSize = true
      updateStyleString()
    }
  }

  public var backgroundColor: UIColor {
    didSet {
      updateStyleString()
    }
  }

  public var interactive: Bool {
    didSet {
      updateStyleString()
    }
  }

  public var active: Bool {
    didSet {
      updateStylePath()
    }
  }

  public func setPointEased(_ coordinates: TGGeoPoint, seconds: Float, easeType ease: TGEaseType) -> Bool {
    return tgMarker.setPointEased(coordinates, seconds: seconds, easeType: ease)
  }


  public static func initWithMarkerType(_ markerType: MarkerType) -> GenericMarker {
    let marker = Marker(markerType: markerType)
    return marker
  }

  public required override init() {
    internalTgMarker = TGMarker.init()
    size = Marker.kDefaultSize
    backgroundColor = Marker.kDefaultBackgroundColor
    interactive = Marker.kDefaultInteractive
    active = Marker.kDefaultActive
  }

  //TODO: add back when https://github.com/tangrams/tangram-es/issues/1394 is fixed
  //  public convenience init(icon i: UIImage?) {
  //    if let sz = i?.size {
  //      self.init(size: sz)
  //    } else {
  //      self.init(size: Marker.kDefaultSize)
  //    }
  //    icon = i
  //  }

  public required init(size s: CGSize) {
    internalTgMarker = TGMarker.init()
    size = s
    backgroundColor = Marker.kDefaultBackgroundColor
    interactive = Marker.kDefaultInteractive
    active = Marker.kDefaultActive
    super.init()<commit_msg>Add Marker documentation<commit_after>//
//  Marker.swift
//  ios-sdk
//
//  Created by <NAME> on 3/22/17.
//  Copyright © 2017 Mapzen. All rights reserved.
//

import Foundation
import TangramMap

/// Enum for common marker types supported by all the house styles.
@objc public enum MarkerType : Int {
  case currentLocation, searchPin, routeLine
}

/// Generic marker protocol definition.
@objc(MZGenericMarker)
public protocol GenericMarker {
  /// The underlying Tangram marker object. Use this only for advanced cases where features of the Marker class aren't supported.
  var tgMarker: TGMarker { get }
  /// The coordinates that the marker should be placed at on the map. Note that point, polyline, and polygon are mutually exclusive. Setting one will overwrite the other values
  var point: TGGeoPoint { get set }
  /// The polyline that should be displayed on the map. Note that point, polyline, and polygon are mutually exclusive. Setting one will overwrite the other values
  var polyline: TGGeoPolyline? { get set }
  /// The polygon that should be displayed on the map. Note that point, polyline, and polygon are mutually exclusive. Setting one will overwrite the other values
  var polygon: TGGeoPolygon? { get set }
  /// The image that should be displayed on the marker. This cannot be used with polylines or polygons, only points.
  var icon: UIImage? { get set }
  /// Toggles the marker visibility.
  var visible: Bool { get set }
  /// The marker draw order relative to other markers. Note that higher values are drawn above lower ones.
  var drawOrder: Int { get set }
  /// Sets the size of a point marker. Does nothing when a polyline or polygon is set.
  var size: CGSize { get set }
  /// Sets the marker background color. Default value is white.
  var backgroundColor: UIColor { get set }
  /// If the marker is interactive, it is able to be selected and delegates can receive callbacks for these events. Default value is true.
  var interactive: Bool { get set }
  /// Should only be used when a marker is initialized with a MarkerType. Updates the visual properties to indicate active status (ie. updates search pin to be gray when inactive).
  var active: Bool { get set }
  /**
   Animates the marker from its current coordinates to the ones given.
   
   - parameter coordinates: Coordinates to animate the marker to
   - parameter seconds: Duration in seconds of the animation.
   - parameter easeType: Easing to use for animation.
  */
  func setPointEased(_ coordinates: TGGeoPoint, seconds: Float, easeType ease: TGEaseType) -> Bool
  /// Returns a marker whose visual properties have been defined by a house style. Do not try to update the background color, size or other visual aspects of this marker.
  static func initWithMarkerType(_ markerType: MarkerType) -> GenericMarker
  /// Default initializer.
  init()
  /**
   Initializes a marker with a given size.
   
   - parameter size: The size the marker should be.
   */
  init(size s: CGSize)
}

/**
 Base implementation for the GenericMarker protocol
 */
public class Marker : NSObject, GenericMarker {

  private static let kPointStyle = "points"
  private static let kLineStyle = "lines"
  private static let kPolygonStyle = "polygons"
  private static let kDefaultBackgroundColor = UIColor.white
  private static let kDefaultInteractive = true
  private static let kDefaultSize = CGSize.zero
  private static let kDefaultActive = true

  var styleType = Marker.kPointStyle
  var markerType: MarkerType?

  // all marker types have an associated styling path
  private let typeToStylingPath = [MarkerType.currentLocation : "layers.mz_current_location_gem.draw.ux-location-gem-overlay",
                                   MarkerType.searchPin : "layers.mz_search_result.draw.ux-icons-overlay",
                                   MarkerType.routeLine : "layers.mz_route_line.draw.ux-route-line-overlay"]
  //currently only search results have an inactive state
  private let typeToInactiveStylingPath = [MarkerType.searchPin : "layers.mz_search_result.inactive.draw.ux-icons-overlay"]

  private let internalTgMarker: TGMarker
  private var userUpdatedSize = false

  /// The underlying Tangram marker object. Use this only for advanced cases where features of the Marker class aren't supported.
  public var tgMarker: TGMarker {
    get {
      return internalTgMarker
    }
  }

  /// The coordinates that the marker should be placed at on the map. Note that point, polyline, and polygon are mutually exclusive. Setting one will overwrite the other values
  public var point: TGGeoPoint {
    set {
      tgMarker.point = newValue
      styleType = Marker.kPointStyle
      updateStyleString()
    }
    get {
      return tgMarker.point
    }
  }

  /// The polyline that should be displayed on the map. Note that point, polyline, and polygon are mutually exclusive. Setting one will overwrite the other values
  public var polyline: TGGeoPolyline? {
    set {
      guard let l  = newValue else { return }
      tgMarker.polyline = l
      styleType = Marker.kLineStyle
      updateStyleString()
    }
    get {
      return tgMarker.polyline
    }
  }

  /// The polygon that should be displayed on the map. Note that point, polyline, and polygon are mutually exclusive. Setting one will overwrite the other values
  public var polygon: TGGeoPolygon? {
    set {
      guard let p = newValue else { return }
      tgMarker.polygon = p
      styleType = Marker.kPolygonStyle
      updateStyleString()
    }
    get {
      return tgMarker.polygon
    }
  }

  /// The image that should be displayed on the marker. Updates the size of the marker to be the intrinsic size of the image. This cannot be used with polylines or polygons, only points.
  public var icon: UIImage? {
    set {
      guard let i = newValue else { return }
      tgMarker.icon = i
      size = i.size
      styleType = Marker.kPointStyle
      updateStyleString()
    }
    get {
      return tgMarker.icon
    }
  }

  /// Toggles the marker visibility.
  public var visible: Bool {
    set {
      tgMarker.visible = newValue
    }
    get {
      return tgMarker.visible
    }
  }

  /// The marker draw order relative to other markers. Note that higher values are drawn above lower ones.
  public var drawOrder: Int {
    set {
      tgMarker.drawOrder = newValue
    }
    get {
      return tgMarker.drawOrder
    }
  }

  /// Sets the size of a point marker. Does nothing when a polyline or polygon is set.
  public var size: CGSize {
    didSet {
      userUpdatedSize = true
      updateStyleString()
    }
  }

  /// Sets the marker background color. Default value is white.
  public var backgroundColor: UIColor {
    didSet {
      updateStyleString()
    }
  }

  /// If the marker is interactive, it is able to be selected and delegates can receive callbacks for these events. Default value is true.
  public var interactive: Bool {
    didSet {
      updateStyleString()
    }
  }

  /// Should only be used when a marker is initialized with a MarkerType. Updates the visual properties to indicate active status (ie. updates search pin to be gray when inactive).
  public var active: Bool {
    didSet {
      updateStylePath()
    }
  }

  /**
   Animates the marker from its current coordinates to the ones given.

   - parameter coordinates: Coordinates to animate the marker to
   - parameter seconds: Duration in seconds of the animation.
   - parameter easeType: Easing to use for animation.
   */
  public func setPointEased(_ coordinates: TGGeoPoint, seconds: Float, easeType ease: TGEaseType) -> Bool {
    return tgMarker.setPointEased(coordinates, seconds: seconds, easeType: ease)
  }

  /// Returns a marker whose visual properties have been defined by a house style. Do not try to update the background color, size or other visual aspects of this marker.
  public static func initWithMarkerType(_ markerType: MarkerType) -> GenericMarker {
    let marker = Marker(markerType: markerType)
    return marker
  }

  /// Default initializer.
  public required override init() {
    internalTgMarker = TGMarker.init()
    size = Marker.kDefaultSize
    backgroundColor = Marker.kDefaultBackgroundColor
    interactive = Marker.kDefaultInteractive
    active = Marker.kDefaultActive
  }

  //TODO: add back when https://github.com/tangrams/tangram-es/issues/1394 is fixed
  //  public convenience init(icon i: UIImage?) {
  //    if let sz = i?.size {
  //      self.init(size: sz)
  //    } else {
  //      self.init(size: Marker.kDefaultSize)
  //    }
  //    icon = i
  //  }

  /**
   Initializes a marker with a given size.

   - parameter size: The size the marker should be.
   */
  public required init(size s: CGSize) {
    internalTgMarker = TGMarker.init()
    size = s
    backgroundColor = Marker.kDefaultBackgroundColor
    interactive = Marker.kDefaultInteractive
    active = Marker.kDefaultActive
    super.init()
{'fraction_non_alphanumeric': 0.07459207459207459, 'fraction_numerical': 0.001893939393939394, 'mean_word_length': 2.8306361607142856, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6153266', 'n_tokens_mistral': 4052, 'n_tokens_neox': 3868, 'n_words': 1422}