'use strict';

var core = require('@pixi/core');
var _const = require('../core/const.js');

const tempArr = [];
function fixOrientation(points, hole = false) {
  const m = points.length;
  if (m < 6) {
    return;
  }
  let area = 0;
  for (let i = 0, x1 = points[m - 2], y1 = points[m - 1]; i < m; i += 2) {
    const x2 = points[i];
    const y2 = points[i + 1];
    area += (x2 - x1) * (y2 + y1);
    x1 = x2;
    y1 = y2;
  }
  if (!hole && area > 0 || hole && area <= 0) {
    const n = m / 2;
    for (let i = n + n % 2; i < m; i += 2) {
      const i1 = m - i - 2;
      const i2 = m - i - 1;
      const i3 = i;
      const i4 = i + 1;
      [points[i1], points[i3]] = [points[i3], points[i1]];
      [points[i2], points[i4]] = [points[i4], points[i2]];
    }
  }
}
class PolyBuilder {
  path(graphicsData, buildData) {
    const shape = graphicsData.shape;
    const points = graphicsData.points = shape.points.slice();
    const eps = buildData.closePointEps;
    const eps2 = eps * eps;
    if (points.length === 0) {
      return;
    }
    const firstPoint = new core.Point(points[0], points[1]);
    const lastPoint = new core.Point(points[points.length - 2], points[points.length - 1]);
    const closedShape = graphicsData.closeStroke = shape.closeStroke;
    let len = points.length;
    let newLen = 2;
    for (let i = 2; i < len; i += 2) {
      const x1 = points[i - 2];
      const y1 = points[i - 1];
      const x2 = points[i];
      const y2 = points[i + 1];
      let flag = true;
      if (Math.abs(x1 - x2) < eps && Math.abs(y1 - y2) < eps) {
        flag = false;
      }
      if (flag) {
        points[newLen] = points[i];
        points[newLen + 1] = points[i + 1];
        newLen += 2;
      }
    }
    points.length = len = newLen;
    newLen = 2;
    for (let i = 2; i + 2 < len; i += 2) {
      let x1 = points[i - 2];
      let y1 = points[i - 1];
      const x2 = points[i];
      const y2 = points[i + 1];
      let x3 = points[i + 2];
      let y3 = points[i + 3];
      x1 -= x2;
      y1 -= y2;
      x3 -= x2;
      y3 -= y2;
      let flag = true;
      if (Math.abs(x3 * y1 - y3 * x1) < eps2) {
        if (x1 * x3 + y1 * y3 < -eps2) {
          flag = false;
        }
      }
      if (flag) {
        points[newLen] = points[i];
        points[newLen + 1] = points[i + 1];
        newLen += 2;
      }
    }
    points[newLen] = points[len - 2];
    points[newLen + 1] = points[len - 1];
    newLen += 2;
    points.length = len = newLen;
    if (len <= 2) {
      return;
    }
    if (closedShape) {
      const closedPath = Math.abs(firstPoint.x - lastPoint.x) < eps && Math.abs(firstPoint.y - lastPoint.y) < eps;
      if (closedPath) {
        points.pop();
        points.pop();
      }
    }
  }
  line(graphicsData, buildData) {
    const { closeStroke, points } = graphicsData;
    const len = points.length;
    if (len <= 2) {
      return;
    }
    const { verts, joints } = buildData;
    const joint = graphicsData.jointType();
    const cap = graphicsData.capType();
    let prevCap = 0;
    let prevX;
    let prevY;
    if (closeStroke) {
      prevX = points[len - 2];
      prevY = points[len - 1];
      joints.push(_const.JOINT_TYPE.NONE);
    } else {
      prevX = points[2];
      prevY = points[3];
      if (cap === _const.JOINT_TYPE.CAP_ROUND) {
        verts.push(points[0], points[1]);
        joints.push(_const.JOINT_TYPE.NONE);
        joints.push(_const.JOINT_TYPE.CAP_ROUND);
        prevCap = 0;
      } else {
        prevCap = cap;
        joints.push(_const.JOINT_TYPE.NONE);
      }
    }
    verts.push(prevX, prevY);
    for (let i = 0; i < len; i += 2) {
      const x1 = points[i];
      const y1 = points[i + 1];
      let endJoint = joint;
      if (i + 2 >= len) {
        if (!closeStroke) {
          endJoint = _const.JOINT_TYPE.NONE;
        }
      } else if (i + 4 >= len) {
        if (!closeStroke) {
          if (cap === _const.JOINT_TYPE.CAP_ROUND) {
            endJoint = _const.JOINT_TYPE.JOINT_CAP_ROUND;
          }
          if (cap === _const.JOINT_TYPE.CAP_BUTT) {
            endJoint = _const.JOINT_TYPE.JOINT_CAP_BUTT;
          }
          if (cap === _const.JOINT_TYPE.CAP_SQUARE) {
            endJoint = _const.JOINT_TYPE.JOINT_CAP_SQUARE;
          }
        }
      }
      endJoint += prevCap;
      prevCap = 0;
      verts.push(x1, y1);
      joints.push(endJoint);
      prevX = x1;
      prevY = y1;
    }
    if (closeStroke) {
      verts.push(points[0], points[1]);
      joints.push(_const.JOINT_TYPE.NONE);
      verts.push(points[2], points[3]);
      joints.push(_const.JOINT_TYPE.NONE);
    } else {
      verts.push(points[len - 4], points[len - 3]);
      joints.push(_const.JOINT_TYPE.NONE);
    }
  }
  fill(graphicsData, buildData) {
    let points = graphicsData.points;
    const holes = graphicsData.holes;
    const eps = buildData.closePointEps;
    const { verts, joints } = buildData;
    if (points.length < 6) {
      return;
    }
    const holeArray = [];
    let len = points.length;
    fixOrientation(points, false);
    for (let i = 0; i < holes.length; i++) {
      const hole = holes[i];
      fixOrientation(hole.points, true);
      holeArray.push(points.length / 2);
      points = points.concat(hole.points);
    }
    const pn = tempArr;
    if (pn.length < points.length) {
      pn.length = points.length;
    }
    let start = 0;
    for (let i = 0; i <= holeArray.length; i++) {
      let finish = len / 2;
      if (i > 0) {
        if (i < holeArray.length) {
          finish = holeArray[i];
        } else {
          finish = points.length >> 1;
        }
      }
      pn[start * 2] = finish - 1;
      pn[(finish - 1) * 2 + 1] = start;
      for (let j = start; j + 1 < finish; j++) {
        pn[j * 2 + 1] = j + 1;
        pn[j * 2 + 2] = j;
      }
      start = finish;
    }
    graphicsData.triangles = core.utils.earcut(points, holeArray, 2);
    if (!graphicsData.triangles) {
      return;
    }
    if (!graphicsData.fillAA) {
      for (let i = 0; i < points.length; i += 2) {
        verts.push(points[i], points[i + 1]);
        joints.push(_const.JOINT_TYPE.FILL);
      }
      return;
    }
    const { triangles } = graphicsData;
    len = points.length;
    for (let i = 0; i < triangles.length; i += 3) {
      let flag = 0;
      for (let j = 0; j < 3; j++) {
        const ind1 = triangles[i + j];
        const ind2 = triangles[i + (j + 1) % 3];
        if (pn[ind1 * 2] === ind2 || pn[ind1 * 2 + 1] === ind2) {
          flag |= 1 << j;
        }
      }
      joints.push(_const.JOINT_TYPE.FILL_EXPAND + flag);
      joints.push(_const.JOINT_TYPE.NONE);
      joints.push(_const.JOINT_TYPE.NONE);
      joints.push(_const.JOINT_TYPE.NONE);
      joints.push(_const.JOINT_TYPE.NONE);
      joints.push(_const.JOINT_TYPE.NONE);
    }
    for (let ind = 0; ind < len / 2; ind++) {
      const prev = pn[ind * 2];
      const next = pn[ind * 2 + 1];
      let nx1 = points[next * 2 + 1] - points[ind * 2 + 1];
      let ny1 = -(points[next * 2] - points[ind * 2]);
      let nx2 = points[ind * 2 + 1] - points[prev * 2 + 1];
      let ny2 = -(points[ind * 2] - points[prev * 2]);
      const D1 = Math.sqrt(nx1 * nx1 + ny1 * ny1);
      nx1 /= D1;
      ny1 /= D1;
      const D2 = Math.sqrt(nx2 * nx2 + ny2 * ny2);
      nx2 /= D2;
      ny2 /= D2;
      let bx = nx1 + nx2;
      let by = ny1 + ny2;
      const D = bx * nx1 + by * ny1;
      if (Math.abs(D) < eps) {
        bx = nx1;
        by = ny1;
      } else {
        bx /= D;
        by /= D;
      }
      pn[ind * 2] = bx;
      pn[ind * 2 + 1] = by;
    }
    for (let i = 0; i < triangles.length; i += 3) {
      const prev = triangles[i];
      const ind = triangles[i + 1];
      const next = triangles[i + 2];
      const nx1 = points[next * 2 + 1] - points[ind * 2 + 1];
      const ny1 = -(points[next * 2] - points[ind * 2]);
      const nx2 = points[ind * 2 + 1] - points[prev * 2 + 1];
      const ny2 = -(points[ind * 2] - points[prev * 2]);
      let j1 = 1;
      if (nx1 * ny2 - nx2 * ny1 > 0) {
        j1 = 2;
      }
      for (let j = 0; j < 3; j++) {
        const ind2 = triangles[i + j * j1 % 3];
        verts.push(points[ind2 * 2], points[ind2 * 2 + 1]);
      }
      for (let j = 0; j < 3; j++) {
        const ind2 = triangles[i + j * j1 % 3];
        verts.push(pn[ind2 * 2], pn[ind2 * 2 + 1]);
      }
    }
  }
}

exports.PolyBuilder = PolyBuilder;
//# sourceMappingURL=PolyBuilder.js.map
