/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.ui.graphics

import androidx.ui.core.toFrameworkRect
import androidx.ui.geometry.Offset
import androidx.ui.geometry.RRect
import androidx.ui.geometry.Radius
import androidx.ui.geometry.Rect
import androidx.ui.graphics.vectormath.Matrix4
import androidx.ui.graphics.vectormath.degrees

class Path(private val internalPath: android.graphics.Path = android.graphics.Path()) {

    // Temporary value holders to reuse an object (not part of a state):
    private val rectF = android.graphics.RectF()
    private val radii = FloatArray(8)
    private val mMatrix = android.graphics.Matrix()

    fun toFrameworkPath(): android.graphics.Path = internalPath

    private fun clone() = Path().apply {
        internalPath.set(this@Path.internalPath)
    }

    /**
     * Determines how the interior of this path is calculated.
     *
     * Defaults to the non-zero winding rule, [PathFillType.nonZero].
     */
    fun getFillType(): PathFillType {
        if (internalPath.fillType == android.graphics.Path.FillType.EVEN_ODD) {
            return PathFillType.evenOdd
        } else {
            return PathFillType.nonZero
        }
    }

    fun setFillType(value: PathFillType) {
        internalPath.fillType =
            if (value == PathFillType.evenOdd) {
                android.graphics.Path.FillType.EVEN_ODD
            } else {
                android.graphics.Path.FillType.WINDING
            }
    }

    /** Starts a new subpath at the given coordinate. */
    fun moveTo(dx: Float, dy: Float) {
        internalPath.moveTo(dx, dy)
    }

    /** Starts a new subpath at the given offset from the current point. */
    fun relativeMoveTo(dx: Float, dy: Float) {
        internalPath.rMoveTo(dx, dy)
    }

    /**
     * Adds a straight line segment from the current point to the given
     * point.
     */
    fun lineTo(dx: Float, dy: Float) {
        internalPath.lineTo(dx, dy)
    }

    /**
     * Adds a straight line segment from the current point to the point
     * at the given offset from the current point.
     */
    fun relativeLineTo(dx: Float, dy: Float) {
        internalPath.rLineTo(dx, dy)
    }

    /**
     * Adds a quadratic bezier segment that curves from the current
     * point to the given point (x2,y2), using the control point
     * (x1,y1).
     */
    fun quadraticBezierTo(x1: Float, y1: Float, x2: Float, y2: Float) {
        internalPath.quadTo(x1, y1, x2, y2)
    }

    /**
     * Adds a quadratic bezier segment that curves from the current
     * point to the point at the offset (x2,y2) from the current point,
     * using the control point at the offset (x1,y1) from the current
     * point.
     */
    fun relativeQuadraticBezierTo(x1: Float, y1: Float, x2: Float, y2: Float) {
        internalPath.rQuadTo(x1, y1, x2, y2)
    }

    /**
     * Adds a cubic bezier segment that curves from the current point
     * to the given point (x3,y3), using the control points (x1,y1) and
     * (x2,y2).
     */
    fun cubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float) {
        internalPath.cubicTo(
            x1, y1,
            x2, y2,
            x3, y3
        )
    }

    /**
     * Adds a cubic bezier segment that curves from the current point
     * to the point at the offset (x3,y3) from the current point, using
     * the control points at the offsets (x1,y1) and (x2,y2) from the
     * current point.
     */
    fun relativeCubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float) {
        internalPath.rCubicTo(
            x1, y1,
            x2, y2,
            x3, y3
        )
    }

    /**
     * Adds a bezier segment that curves from the current point to the
     * given point (x2,y2), using the control points (x1,y1) and the
     * weight w. If the weight is greater than 1, then the curve is a
     * hyperbola; if the weight equals 1, it's a parabola; and if it is
     * less than 1, it is an ellipse.
     *
     * Throws [UnsupportedOperationException] as Android framework does not support this API
     */
    @Suppress("UNUSED_PARAMETER")
    fun conicTo(x1: Float, y1: Float, x2: Float, y2: Float, w: Float) {
        // TODO(njawad) figure out how to handle unsupported framework Path operations
        throw UnsupportedOperationException("conicTo not supported in framework Path")
    }

    /**
     * Adds a bezier segment that curves from the current point to the
     * point at the offset (x2,y2) from the current point, using the
     * control point at the offset (x1,y1) from the current point and
     * the weight w. If the weight is greater than 1, then the curve is
     * a hyperbola; if the weight equals 1, it's a parabola; and if it
     * is less than 1, it is an ellipse.
     *
     * Throws [UnsupportedOperationException] as Android framework does not support this API
     */
    @Suppress("UNUSED_PARAMETER")
    fun relativeConicTo(x1: Float, y1: Float, x2: Float, y2: Float, w: Float) {
        // TODO(njawad) figure out how to handle unsupported framework Path operations
        throw UnsupportedOperationException("relativeConicTo not supported in framework Path")
    }

    /**
     * If the [forceMoveTo] argument is false, adds a straight line
     * segment and an arc segment.
     *
     * If the [forceMoveTo] argument is true, starts a new subpath
     * consisting of an arc segment.
     *
     * In either case, the arc segment consists of the arc that follows
     * the edge of the oval bounded by the given rectangle, from
     * startAngle radians around the oval up to startAngle + sweepAngle
     * radians around the oval, with zero radians being the point on
     * the right hand side of the oval that crosses the horizontal line
     * that intersects the center of the rectangle and with positive
     * angles going clockwise around the oval.
     *
     * The line segment added if `forceMoveTo` is false starts at the
     * current point and ends at the start of the arc.
     */
    fun arcToRad(
        rect: Rect,
        startAngleRadians: Float,
        sweepAngleRadians: Float,
        forceMoveTo: Boolean
    ) {
        arcTo(rect, degrees(startAngleRadians), degrees(sweepAngleRadians), forceMoveTo)
    }

    /**
     * If the [forceMoveTo] argument is false, adds a straight line
     * segment and an arc segment.
     *
     * If the [forceMoveTo] argument is true, starts a new subpath
     * consisting of an arc segment.
     *
     * In either case, the arc segment consists of the arc that follows
     * the edge of the oval bounded by the given rectangle, from
     * startAngle degrees around the oval up to startAngle + sweepAngle
     * degrees around the oval, with zero degrees being the point on
     * the right hand side of the oval that crosses the horizontal line
     * that intersects the center of the rectangle and with positive
     * angles going clockwise around the oval.
     *
     * The line segment added if `forceMoveTo` is false starts at the
     * current point and ends at the start of the arc.
     */
    fun arcTo(
        rect: Rect,
        startAngleDegrees: Float,
        sweepAngleDegrees: Float,
        forceMoveTo: Boolean
    ) {
        val left = rect.left
        val top = rect.top
        val right = rect.right
        val bottom = rect.bottom
        rectF.set(left, top, right, bottom)
        internalPath.arcTo(
            rectF,
            startAngleDegrees,
            sweepAngleDegrees,
            forceMoveTo
        )
    }

    /**
     * Appends up to four conic curves weighted to describe an oval of `radius`
     * and rotated by `rotation`.
     *
     * The first curve begins from the last point in the path and the last ends
     * at `arcEnd`. The curves follow a path in a direction determined by
     * `clockwise` and `largeArc` in such a way that the sweep angle
     * is always less than 360 degrees.
     *
     * A simple line is appended if either either radii are zero or the last
     * point in the path is `arcEnd`. The radii are scaled to fit the last path
     * point if both are greater than zero but too small to describe an arc.
     *
     * Throws [UnsupportedOperationException] as Android framework does not support this API
     */
    @Suppress("UNUSED_PARAMETER")
    fun arcToPoint(
        arcEnd: Offset,
        radius: Radius = Radius.zero,
        rotation: Float = 0.0f,
        largeArc: Boolean = false,
        clockwise: Boolean = true
    ) {
        // TODO(njawad) figure out how to handle unsupported framework Path operations
        throw UnsupportedOperationException("arcToPoint not supported in framework Path")
    }

    @Suppress("UNUSED_PARAMETER")
    private fun _arcToPoint(
        arcEndX: Float,
        arcEndY: Float,
        radius: Float,
        radiusY: Float,
        rotation: Float,
        largeArc: Boolean,
        clockwise: Boolean
    ) {
        // TODO(njawad): figure out how to handle unsupported framework Path operations)
        TODO()
        // Flutter calls into native Path logic here
        // native 'Path_arcToPoint'
    }

    /**
     * Appends up to four conic curves weighted to describe an oval of `radius`
     * and rotated by `rotation`.
     *
     * The last path point is described by (px, py).
     *
     * The first curve begins from the last point in the path and the last ends
     * at `arcEndDelta.dx + px` and `arcEndDelta.dy + py`. The curves follow a
     * path in a direction determined by `clockwise` and `largeArc`
     * in such a way that the sweep angle is always less than 360 degrees.
     *
     * A simple line is appended if either either radii are zero, or, both
     * `arcEndDelta.dx` and `arcEndDelta.dy` are zero. The radii are scaled to
     * fit the last path point if both are greater than zero but too small to
     * describe an arc.
     */
    fun relativeArcToPoint(
        arcEndDelta: Offset,
        radius: Radius = Radius.zero,
        rotation: Float = 0.0f,
        largeArc: Boolean = false,
        clockwise: Boolean = true
    ) {
        _relativeArcToPoint(
            arcEndDelta.dx,
            arcEndDelta.dy,
            radius.x,
            radius.y,
            rotation,
            largeArc,
            clockwise
        )
    }

    @Suppress("UNUSED_PARAMETER")
    private fun _relativeArcToPoint(
        arcEndX: Float,
        arcEndY: Float,
        radius: Float,
        radiusY: Float,
        rotation: Float,
        largeArc: Boolean,
        clockwise: Boolean
    ) {
        // TODO(njawad): figure out how to handle unsupported framework Path operations)
        TODO()
        // Flutter calls into native Path logic here
        // native 'Path_relativeArcToPoint';
    }

    /**
     * Adds a new subpath that consists of four lines that outline the
     * given rectangle.
     */
    fun addRect(rect: Rect) {
        assert(_rectIsValid(rect))
        rectF.set(rect.toFrameworkRect())
        // TODO(njawad) figure out what to do with Path Direction,
        // Flutter does not use it, Platform does
        internalPath.addRect(rectF, android.graphics.Path.Direction.CCW)
    }

    // Not necessary as wrapping platform Path
    @Suppress("UNUSED_PARAMETER")
    fun _addRect(left: Float, top: Float, right: Float, bottom: Float) {
        TODO()
        // Flutter calls into native Path logic here
        // native 'Path_addRect';
    }

    /**
     * Adds a new subpath that consists of a curve that forms the
     * ellipse that fills the given rectangle.
     *
     * To add a circle, pass an appropriate rectangle as `oval`. [Rect.fromCircle]
     * can be used to easily describe the circle's center [Offset] and radius.
     */
    fun addOval(oval: Rect) {
        rectF.set(oval.toFrameworkRect())
        // TODO(njawad): figure out what to do with Path Direction,
        // Flutter does not use it, Platform does)
        internalPath.addOval(rectF, android.graphics.Path.Direction.CCW)
        // _addOval(oval.left, oval.top, oval.right, oval.bottom);
    }

    // Not necessary as wrapping platform Path
    @Suppress("UNUSED_PARAMETER")
    private fun _addOval(left: Float, top: Float, right: Float, bottom: Float) {
        TODO()
        // Flutter calls into native Path logic here
        // native 'Path_addOval';
    }

    /**
     * Adds a new subpath with one arc segment that consists of the arc
     * that follows the edge of the oval bounded by the given
     * rectangle, from startAngle radians around the oval up to
     * startAngle + sweepAngle radians around the oval, with zero
     * radians being the point on the right hand side of the oval that
     * crosses the horizontal line that intersects the center of the
     * rectangle and with positive angles going clockwise around the
     * oval.
     */
    fun addArcRad(oval: Rect, startAngleRadians: Float, sweepAngleRadians: Float) {
        addArc(oval, degrees(startAngleRadians), degrees(sweepAngleRadians))
    }

    /**
     * Adds a new subpath with one arc segment that consists of the arc
     * that follows the edge of the oval bounded by the given
     * rectangle, from startAngle degrees around the oval up to
     * startAngle + sweepAngle degrees around the oval, with zero
     * degrees being the point on the right hand side of the oval that
     * crosses the horizontal line that intersects the center of the
     * rectangle and with positive angles going clockwise around the
     * oval.
     */
    fun addArc(oval: Rect, startAngleDegrees: Float, sweepAngleDegrees: Float) {
        assert(_rectIsValid(oval))
        rectF.set(oval.toFrameworkRect())
        internalPath.addArc(rectF, startAngleDegrees, sweepAngleDegrees)
    }

    // Not necessary as wrapping platform Path
    @Suppress("UNUSED_PARAMETER")
    private fun _addArc(left: Float, top: Float, right: Float, bottom: Float) {
        TODO()
        // Flutter calls into native Path logic here
        // native 'Path_addArc'
    }

    /**
     * Adds a new subpath with a sequence of line segments that connect the given
     * points.
     *
     * If `close` is true, a final line segment will be added that connects the
     * last point to the first point.
     *
     * The `points` argument is interpreted as offsets from the origin.
     */
    @Suppress("UNUSED_PARAMETER")
    fun addPolygon(points: List<Offset>, close: Boolean) {
        // TODO(njawad) implement with sequence of "lineTo" calls
        TODO()
    }

    @Suppress("UNUSED_PARAMETER")
    private fun _addPolygon(points: FloatArray, close: Boolean) {
        // TODO(njawad): implement with sequence of "lineTo" calls)
        TODO()
        // Flutter calls into native code here
        // native 'Path_addPolygon'
    }

    fun addRRect(rrect: RRect) {
        rectF.set(rrect.left, rrect.top, rrect.right, rrect.bottom)
        radii[0] = rrect.topLeftRadiusX
        radii[1] = rrect.topLeftRadiusY

        radii[2] = rrect.topRightRadiusX
        radii[3] = rrect.topRightRadiusY

        radii[4] = rrect.bottomRightRadiusX
        radii[5] = rrect.bottomRightRadiusY

        radii[6] = rrect.bottomLeftRadiusX
        radii[7] = rrect.bottomLeftRadiusY
        internalPath.addRoundRect(rectF, radii, android.graphics.Path.Direction.CCW)
    }

    // Not necessary as wrapping platform Path
    @Suppress("UNUSED_PARAMETER")
    private fun _addRRect(rrect: FloatArray) {
        TODO()
        // Flutter calls into native Path logic here
        // native 'Path_addRRect';
    }

    /**
     * Adds a new subpath that consists of the given `path` offset by the given
     * `offset`.
     *
     * If `matrix4` is specified, the path will be transformed by this matrix
     * after the matrix is translated by the given offset. The matrix is a 4x4
     * matrix stored in column major order.
     */
    fun addPath(path: Path, offset: Offset = Offset.zero, matrix: Matrix4? = null) {
        if (matrix != null) {
            // TODO(njawad): update logic to convert Matrix4 -> framework
            // Matrix when ported)
            TODO("Refactor to convert Matrix4 to framework Matrix when Matrix4 is ported")
            // internalPath.addPath(path.toFrameworkPath(), matrix);
        } else {
            internalPath.addPath(path.toFrameworkPath(), offset.dx, offset.dy)
        }
    }

    // Not necessary as wrapping platform Path
    @Suppress("UNUSED_PARAMETER")
    private fun _addPath(path: Path, dx: Float, dy: Float) {
        TODO()
        // Flutter calls into native Path logic here
        // native 'Path_addPath';
    }

    // Not necessary as wrapping platform Path
    @Suppress("UNUSED_PARAMETER")
    private fun _addPathWithMatrix(path: Path, dx: Float, dy: Float, matrix4: Matrix4) {
        TODO()
        // Flutter calls into native Path logic here
        // native 'Path_addPathWithMatrix';
    }

    fun extendWithPath(path: Path, offset: Offset, matrix: Matrix4) {
        assert(Offset.isValid(offset))
//        if (matrix != null) {
            assert(_matrixIsValid(matrix))
            _extendWithPathAndMatrix(path, offset.dx, offset.dy, matrix)
//        } else {
//            _extendWithPath(path, offset.dx, offset.dy)
//        }
    }

    @Suppress("UNUSED_PARAMETER")
    private fun _extendWithPath(path: Path, dx: Float, dy: Float) {
        // TODO(njawad): figure out how to handle unsupported framework Path operations)
        TODO()
        // Flutter calls into native Path logic here
        // native 'Path_extendWithPath';
    }

    @Suppress("UNUSED_PARAMETER")
    private fun _extendWithPathAndMatrix(path: Path, dx: Float, dy: Float, matrix: Matrix4) {
        // TODO(njawad): figure out how to handle unsupported framework Path operations)
        TODO()
        // Flutter calls into native Path logic here
        // native 'Path_extendWithPathAndMatrix';
    }

    /**
     * Closes the last subpath, as if a straight line had been drawn
     * from the current point to the first point of the subpath.
     */
    fun close() {
        internalPath.close()
    }

    /**
     * Clears the [Path] object of all subpaths, returning it to the
     * same state it had when it was created. The _current point_ is
     * reset to the origin.
     */
    fun reset() {
        internalPath.reset()
    }

    /**
     * Tests to see if the given point is within the path. (That is, whether the
     * point would be in the visible portion of the path if the path was used
     * with [Canvas.clipPath].)
     *
     * The `point` argument is interpreted as an offset from the origin.
     *
     * Returns true if the point is in the path, and false otherwise.
     */
    fun contains(offset: Offset): Boolean {
        assert(Offset.isValid(offset))
        return _contains(offset)
    }

    private fun _contains(offset: Offset): Boolean {
        // TODO(njawad) framework Path implementation does not have a contains method")
        // TODO(njawad): figure out how to handle unsupported framework Path operations)

        // TODO(Andrey): temporary non-efficient implementation)
        val path = android.graphics.Path()
        path.addRect(
            offset.dx - 0.01f,
            offset.dy - 0.01f,
            offset.dx + 0.01f,
            offset.dy + 0.01f,
            android.graphics.Path.Direction.CW
        )
        if (path.op(internalPath, android.graphics.Path.Op.INTERSECT)) {
            return !path.isEmpty
        }
        return false
        // Flutter calls into native code here
        // native 'Path_contains';
    }

    /**
     * Translates all the segments of every subpath by the given offset.
     */
    fun shift(offset: Offset) {
        mMatrix.reset()
        mMatrix.setTranslate(offset.dx, offset.dy)
        internalPath.transform(mMatrix)
    }

    /**
     * Returns a copy of the path with all the segments of every
     * subpath transformed by the given matrix.
     */
    @Suppress("UNUSED_PARAMETER")
    fun transform(matrix: Matrix4): Path {
        // TODO(njawad): Update implementation with Matrix4 -> android.graphics.Matrix)
        TODO("Update implementation with Matrix4 -> android.graphics.Matrix conversion")
        // internalPath.transform(matrix);
//        return clone()
    }

    // Not necessary as ported implementation with public transform method
    @Suppress("UNUSED_PARAMETER")
    private fun _transform(matrix: Matrix4) {
        TODO()
        // Flutter calls into native code here
        // native 'Path_transform';
    }

    /**
     * Computes the bounding rectangle for this path.
     *
     * A path containing only axis-aligned points on the same straight line will
     * have no area, and therefore `Rect.isEmpty` will return true for such a
     * path. Consider checking `rect.width + rect.height > 0.0` instead, or
     * using the [computeMetrics] API to check the path length.
     *
     * For many more elaborate paths, the bounds may be inaccurate.  For example,
     * when a path contains a circle, the points used to compute the bounds are
     * the circle's implied control points, which form a square around the circle;
     * if the circle has a transformation applied using [transform] then that
     * square is rotated, and the (axis-aligned, non-rotated) bounding box
     * therefore ends up grossly overestimating the actual area covered by the
     * circle.
     */
    // see https://skia.org/user/api/SkPath_Reference#SkPath_getBounds
    fun getBounds(): Rect {
        internalPath.computeBounds(rectF, true)
        return Rect(
                rectF.left,
                rectF.top,
                rectF.right,
                rectF.bottom
        )
    }

    // Not necessary as implemented with framework Path#computeBounds method
    private fun _getBounds(): Rect {
        TODO()
        // Flutter calls into native code here
        // native 'Path_getBounds';
//        return Rect(0.0f, 0.0f, 0.0f, 0.0f)
    }

    companion object {
        /**
         * Combines the two paths according to the manner specified by the given
         * `operation`.
         *
         * The resulting path will be constructed from non-overlapping contours. The
         * curve order is reduced where possible so that cubics may be turned into
         * quadratics, and quadratics maybe turned into lines.
         *
         * Throws [IllegalArgumentException] as Android framework does not support this API
         */
        fun combine(
            operation: PathOperation,
            path1: Path,
            path2: Path
        ): Path {
            val path = Path()

            if (path.op(path1, path2, operation)) {
                return path
            }
            throw IllegalArgumentException("Path.combine() failed.  This may be due an invalid " +
                    "path; in particular, check for NaN values.")
            // TODO(njawad) where do we put Dart's StateError or equivalent?
            // throw StateError('Path.combine() failed.  This may be due an invalid path;
            // in particular, check for NaN values.');
        }
    }

    // Wrapper around _op method to avoid synthetic accessor in companion combine method
    fun op(
        path1: Path,
        path2: Path,
        operation: PathOperation
    ): Boolean {
        return _op(path1, path2, operation)
    }

    private fun _op(
        path1: Path,
        path2: Path,
        operation: PathOperation
    ): Boolean {
        // TODO(shepshapard): Our current min SDK is 21, so this check shouldn't be needed.
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            val op = when (operation) {
                PathOperation.difference -> android.graphics.Path.Op.DIFFERENCE
                PathOperation.intersect -> android.graphics.Path.Op.INTERSECT
                PathOperation.reverseDifference -> android.graphics.Path.Op.REVERSE_DIFFERENCE
                PathOperation.union -> android.graphics.Path.Op.UNION
                else -> android.graphics.Path.Op.XOR
            }
            return internalPath.op(path1.toFrameworkPath(), path2.toFrameworkPath(), op)
//        } else {
//            return false
//        }
    }

    // TODO(njawad) figure out equivalent for PathMetrics for the framework based in Path
//
//    // / Creates a [PathMetrics] object for this path.
//    // /
//    // / If `forceClosed` is set to true, the contours of the path will be measured
//    // / as if they had been closed, even if they were not explicitly closed.
//    PathMetrics computeMetrics({bool forceClosed: false}) {
//        return new PathMetrics._(this, forceClosed);
//    }

    /**
     * Returns the path's convexity, as defined by the content of the path.
     *
     * A path is convex if it has a single contour, and only ever curves in a
     * single direction.
     *
     * This function will calculate the convexity of the path from its control
     * points, and cache the result.
     */
    val isConvex: Boolean get() = internalPath.isConvex

    /**
     * Returns true if the path is empty (contains no lines or curves)
     */
    val isEmpty: Boolean get() = internalPath.isEmpty

    private fun _rectIsValid(rect: Rect): Boolean {
        assert(Float.NaN != rect.left) {
            "Rect.left is NaN"
        }
        assert(Float.NaN != rect.top) {
            "Rect.top is NaN"
        }
        assert(Float.NaN != rect.right) {
            "Rect.right is NaN"
        }
        assert(Float.NaN != rect.bottom) {
            "Rect.bottom is NaN"
        }
        return true
    }

    @Suppress("UNUSED_PARAMETER")
    private fun _matrixIsValid(matrix: Matrix4): Boolean {
        return true
    }
}
