//
//  PopoverView.swift
//  KeymanEngine
//
//  Created by Gabriel Wong on 2017-09-11.
//  Copyright © 2017 SIL International. All rights reserved.
//

import UIKit

class PopoverView: UIView {
  let strokeWidth: CGFloat = 2.0
  let arrowWidth: CGFloat = 21.0
  let arrowHeight: CGFloat = 7.0
  let borderRadius: CGFloat = 5.0
  var borderColor = Colors.popupBorder

  // A default color.  This class's current only use will override these values.
  private var bgColor = Colors.systemBackground
  var backgroundColor2 = Colors.systemBackground
  private var _arrowPosX: CGFloat = 0.0

  override init(frame: CGRect) {
    super.init(frame: frame)
    super.backgroundColor = UIColor.clear
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  override func draw(_ rect: CGRect) {
    guard let context = UIGraphicsGetCurrentContext() else {
      return
    }
    UIGraphicsPushContext(context)
    let currentFrame = bounds

    context.setLineJoin(CGLineJoin.round)
    context.setLineWidth(strokeWidth)
    context.setStrokeColor(borderColor.cgColor)
    context.setFillColor(bgColor.cgColor)

    context.beginPath()
    let arrowPosY: CGFloat = currentFrame.size.height - (arrowHeight + strokeWidth)
    context.move(to: CGPoint(x: borderRadius + strokeWidth, y: arrowPosY))
    context.addLine(to: CGPoint(x: arrowPosX - arrowWidth / 2.0, y: arrowPosY))
    context.addLine(to: CGPoint(x: arrowPosX, y: currentFrame.size.height - strokeWidth))
    context.addLine(to: CGPoint(x: arrowPosX + arrowWidth / 2.0, y: arrowPosY))
    context.addArc(tangent1End: CGPoint(x: currentFrame.size.width - strokeWidth,
                                        y: arrowPosY),
                   tangent2End: CGPoint(x: currentFrame.size.width - strokeWidth,
                                        y: strokeWidth),
                   radius: borderRadius - strokeWidth)
    context.addArc(tangent1End: CGPoint(x: currentFrame.size.width - strokeWidth,
                                        y: strokeWidth),
                   tangent2End: CGPoint(x: round(currentFrame.size.width / 2.0 +
                      arrowWidth / 2.0) - strokeWidth,
                                        y: strokeWidth),
                   radius: borderRadius - strokeWidth)
    context.addArc(tangent1End: CGPoint(x: strokeWidth, y: strokeWidth),
                   tangent2End: CGPoint(x: strokeWidth, y: arrowPosY),
                   radius: borderRadius - strokeWidth)
    context.addArc(tangent1End: CGPoint(x: strokeWidth, y: arrowPosY),
                   tangent2End: CGPoint(x: currentFrame.size.width - strokeWidth,
                                        y: arrowPosY),
                   radius: borderRadius - strokeWidth)
    context.closePath()
    context.drawPath(using: CGPathDrawingMode.fillStroke)

    context.beginPath()
    context.move(to: CGPoint(x: borderRadius + strokeWidth, y: arrowPosY))
    context.addLine(to: CGPoint(x: arrowPosX - arrowWidth / 2.0, y: arrowPosY))
    context.addLine(to: CGPoint(x: arrowPosX, y: currentFrame.size.height - strokeWidth))
    context.addLine(to: CGPoint(x: arrowPosX + arrowWidth / 2.0, y: arrowPosY))
    context.addArc(tangent1End: CGPoint(x: currentFrame.size.width - strokeWidth,
                                        y: arrowPosY),
                   tangent2End: CGPoint(x: currentFrame.size.width - strokeWidth,
                                        y: strokeWidth),
                   radius: borderRadius - strokeWidth)
    context.addArc(tangent1End: CGPoint(x: currentFrame.size.width - strokeWidth,
                                        y: strokeWidth),
                   tangent2End: CGPoint(x: round(currentFrame.size.width / 2.0 +
                       arrowWidth / 2.0) - strokeWidth,
                                        y: strokeWidth),
                   radius: borderRadius - strokeWidth)
    context.addArc(tangent1End: CGPoint(x: strokeWidth, y: strokeWidth),
                   tangent2End: CGPoint(x: strokeWidth, y: arrowPosY),
                   radius: borderRadius - strokeWidth)
    context.addArc(tangent1End: CGPoint(x: strokeWidth, y: arrowPosY),
                   tangent2End: CGPoint(x: currentFrame.size.width - strokeWidth,
                                        y: arrowPosY),
                   radius: borderRadius - strokeWidth)
    context.closePath()
    context.clip()

    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let gradientColors = [bgColor.cgColor, backgroundColor2.cgColor] as CFArray
    let gradientLocations: [CGFloat] = [0, 1]
    let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors,
                                    locations: gradientLocations)!

    let startPoint = CGPoint(x: rect.midX, y: rect.minY)
    let endPoint = CGPoint(x: rect.midX, y: rect.maxY)

    context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: [])
    UIGraphicsPopContext()
  }

  override var backgroundColor: UIColor? {
    get {
      return super.backgroundColor
    }

    set(color) {
      super.backgroundColor = UIColor.clear
      if let color = color {
        bgColor = color
      }
    }
  }

  var arrowPosX: CGFloat {
    get {
      return _arrowPosX
    }

    set(posX) {
      let currentFrame = bounds
      if posX < (arrowWidth / 2.0 + borderRadius + strokeWidth) {
        _arrowPosX = arrowWidth / 2.0 + borderRadius + strokeWidth
      } else if posX > (currentFrame.size.width - arrowWidth / 2.0 - borderRadius - strokeWidth) {
        _arrowPosX = currentFrame.size.width - arrowWidth / 2.0 - borderRadius - strokeWidth
      } else {
        _arrowPosX = posX
      }
      setNeedsDisplay()
    }
  }
}
