// Generated by ReScript, PLEASE EDIT WITH CARE

import * as P from "./P.js";
import * as Caml from "rescript/lib/es6/caml.js";
import * as List from "rescript/lib/es6/list.js";
import * as Curry from "rescript/lib/es6/curry.js";
import * as $$Buffer from "rescript/lib/es6/buffer.js";
import * as Format from "./format.js";
import * as $$String from "rescript/lib/es6/string.js";
import * as Caml_sys from "rescript/lib/es6/caml_sys.js";
import * as $$Location from "./location.js";
import * as Pervasives from "rescript/lib/es6/pervasives.js";
import * as Caml_option from "rescript/lib/es6/caml_option.js";
import * as Caml_string from "rescript/lib/es6/caml_string.js";
import * as Caml_js_exceptions from "rescript/lib/es6/caml_js_exceptions.js";
import * as Caml_external_polyfill from "rescript/lib/es6/caml_external_polyfill.js";

function digits_count(n) {
  var n$1 = Pervasives.abs(n);
  var _base = 1;
  var _count = 0;
  while(true) {
    var count = _count;
    var base = _base;
    if (n$1 < base) {
      return count;
    }
    _count = count + 1 | 0;
    _base = Math.imul(base, 10);
    continue ;
  };
}

function seek_2_lines_before(src, pos) {
  var original_line = pos.pos_lnum;
  var _current_line = 1;
  var _current_char = 0;
  while(true) {
    var current_char = _current_char;
    var current_line = _current_line;
    if ((current_line + 2 | 0) >= original_line) {
      return [
              current_char,
              current_line
            ];
    }
    _current_char = current_char + 1 | 0;
    _current_line = Caml_string.get(src, current_char) === /* '\n' */10 ? current_line + 1 | 0 : current_line;
    continue ;
  };
}

function seek_2_lines_after(src, pos) {
  var original_line = pos.pos_lnum;
  var _current_line = original_line;
  var _current_char = pos.pos_cnum;
  while(true) {
    var current_char = _current_char;
    var current_line = _current_line;
    if (current_char === src.length) {
      return [
              current_char,
              current_line
            ];
    }
    var match = Caml_string.get(src, current_char);
    if (match !== 10) {
      _current_char = current_char + 1 | 0;
      continue ;
    }
    if (current_line === (original_line + 2 | 0)) {
      return [
              current_char,
              current_line
            ];
    }
    _current_char = current_char + 1 | 0;
    _current_line = current_line + 1 | 0;
    continue ;
  };
}

function leading_space_count(str) {
  var _i = 0;
  var _count = 0;
  while(true) {
    var count = _count;
    var i = _i;
    if (i === str.length) {
      return count;
    }
    if (Caml_string.get(str, i) !== /* ' ' */32) {
      return count;
    }
    _count = count + 1 | 0;
    _i = i + 1 | 0;
    continue ;
  };
}

function break_long_line(max_width, line) {
  var loop = function (_pos, _accum) {
    while(true) {
      var accum = _accum;
      var pos = _pos;
      if (pos === line.length) {
        return accum;
      }
      var chunk_length = Caml.caml_int_min(max_width, line.length - pos | 0);
      var chunk = $$String.sub(line, pos, chunk_length);
      _accum = {
        hd: chunk,
        tl: accum
      };
      _pos = pos + chunk_length | 0;
      continue ;
    };
  };
  return List.rev(loop(0, /* [] */0));
}

function filter_mapi(f, l) {
  var loop = function (f, _l, _i, _accum) {
    while(true) {
      var accum = _accum;
      var i = _i;
      var l = _l;
      if (!l) {
        return accum;
      }
      var result = Curry._2(f, i, l.hd);
      var accum$1 = result !== undefined ? ({
            hd: Caml_option.valFromOption(result),
            tl: accum
          }) : accum;
      _accum = accum$1;
      _i = i + 1 | 0;
      _l = l.tl;
      continue ;
    };
  };
  return List.rev(loop(f, l, 0, /* [] */0));
}

var dim = "\x11[2m";

var err = "\x11[1;31m";

var warn = "\x11[1;33m";

var reset = "\x11[0m";

function should_enable_color(param) {
  var term;
  try {
    term = Caml_sys.caml_sys_getenv("TERM");
  }
  catch (raw_exn){
    var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
    if (exn.RE_EXN_ID === "Not_found") {
      term = "";
    } else {
      throw exn;
    }
  }
  if (term !== "dumb" && term !== "") {
    return Caml_external_polyfill.resolve("caml_sys_isatty")(P.stderr);
  } else {
    return false;
  }
}

var color_enabled = {
  contents: true
};

var first = {
  contents: true
};

function setup(o) {
  if (first.contents) {
    first.contents = false;
    var tmp;
    if (o !== undefined) {
      switch (o) {
        case /* Auto */0 :
            tmp = should_enable_color(undefined);
            break;
        case /* Always */1 :
            tmp = true;
            break;
        case /* Never */2 :
            tmp = false;
            break;
        
      }
    } else {
      tmp = should_enable_color(undefined);
    }
    color_enabled.contents = tmp;
  }
  
}

var Color = {
  dim: dim,
  err: err,
  warn: warn,
  reset: reset,
  should_enable_color: should_enable_color,
  color_enabled: color_enabled,
  setup: setup
};

function print(is_warning, src, startPos, endPos) {
  var highlight_line_start_line = startPos.pos_lnum;
  var highlight_line_end_line = endPos.pos_lnum;
  var match = seek_2_lines_before(src, startPos);
  var first_shown_line = match[1];
  var start_line_line_offset = match[0];
  var match$1 = seek_2_lines_after(src, endPos);
  var more_than_5_highlighted_lines = ((highlight_line_end_line - highlight_line_start_line | 0) + 1 | 0) > 5;
  var max_line_digits_count = digits_count(match$1[1]);
  var line_width = ((78 - max_line_digits_count | 0) - 2 | 0) - 3 | 0;
  var lines = filter_mapi((function (i, line) {
          var line_number = i + first_shown_line | 0;
          if (more_than_5_highlighted_lines) {
            if (line_number === (highlight_line_start_line + 2 | 0)) {
              return [
                      /* Elided */0,
                      line
                    ];
            } else if (line_number > (highlight_line_start_line + 2 | 0) && line_number < (highlight_line_end_line - 1 | 0)) {
              return ;
            } else {
              return [
                      /* Number */{
                        _0: line_number
                      },
                      line
                    ];
            }
          } else {
            return [
                    /* Number */{
                      _0: line_number
                    },
                    line
                  ];
          }
        }), $$String.split_on_char(/* '\n' */10, $$String.sub(src, start_line_line_offset, match$1[0] - start_line_line_offset | 0)));
  var leading_space_to_cut = List.fold_left((function (current_max, param) {
          var line = param[1];
          var leading_spaces = leading_space_count(line);
          if (line.length === leading_spaces || leading_spaces >= current_max) {
            return current_max;
          } else {
            return leading_spaces;
          }
        }), 99999, lines);
  var separator = leading_space_to_cut === 0 ? "\xe2\x94\x82" : "\xe2\x94\x86";
  var stripped_lines = List.map((function (param) {
          var line = param[1];
          var gutter = param[0];
          var new_content = line.length <= leading_space_to_cut ? ({
                hd: {
                  s: "",
                  start: 0,
                  end_: 0
                },
                tl: /* [] */0
              }) : List.mapi((function (i, line) {
                    if (!gutter) {
                      return {
                              s: line,
                              start: 0,
                              end_: 0
                            };
                    }
                    var line_number = gutter._0;
                    var highlight_line_start_offset = startPos.pos_cnum - startPos.pos_bol | 0;
                    var highlight_line_end_offset = endPos.pos_cnum - endPos.pos_bol | 0;
                    var start = i === 0 && line_number === highlight_line_start_line ? highlight_line_start_offset - leading_space_to_cut | 0 : 0;
                    var end_ = line_number < highlight_line_start_line ? 0 : (
                        line_number === highlight_line_start_line && line_number === highlight_line_end_line ? highlight_line_end_offset - leading_space_to_cut | 0 : (
                            line_number === highlight_line_start_line ? line.length : (
                                line_number > highlight_line_start_line && line_number < highlight_line_end_line ? line.length : (
                                    line_number === highlight_line_end_line ? highlight_line_end_offset - leading_space_to_cut | 0 : 0
                                  )
                              )
                          )
                      );
                    return {
                            s: line,
                            start: start,
                            end_: end_
                          };
                  }), break_long_line(line_width, $$String.sub(line, leading_space_to_cut, line.length - leading_space_to_cut | 0)));
          return {
                  gutter: gutter,
                  content: new_content
                };
        }), lines);
  var buf = $$Buffer.create(100);
  var last_color = {
    contents: /* NoColor */3
  };
  var add_ch = function (color, ch) {
    if (!color_enabled.contents || last_color.contents === color) {
      return $$Buffer.add_char(buf, ch);
    }
    var match = last_color.contents;
    var ansi;
    var exit = 0;
    if (match >= 3) {
      switch (color) {
        case /* Dim */0 :
            ansi = dim;
            break;
        case /* Err */1 :
            ansi = err;
            break;
        case /* Warn */2 :
            ansi = warn;
            break;
        case /* NoColor */3 :
            exit = 1;
            break;
        
      }
    } else {
      exit = 1;
    }
    if (exit === 1) {
      switch (color) {
        case /* Dim */0 :
            ansi = "\x11[0m\x11[2m";
            break;
        case /* Err */1 :
            ansi = "\x11[0m\x11[1;31m";
            break;
        case /* Warn */2 :
            ansi = "\x11[0m\x11[1;33m";
            break;
        case /* NoColor */3 :
            ansi = reset;
            break;
        
      }
    }
    $$Buffer.add_string(buf, ansi);
    $$Buffer.add_char(buf, ch);
    last_color.contents = color;
    
  };
  var draw_gutter = function (color, s) {
    for(var _i = 1 ,_i_finish = (max_line_digits_count + 2 | 0) - s.length | 0; _i <= _i_finish; ++_i){
      add_ch(/* NoColor */3, /* ' ' */32);
    }
    $$String.iter((function (param) {
            return add_ch(color, param);
          }), s);
    add_ch(/* NoColor */3, /* ' ' */32);
    $$String.iter((function (param) {
            return add_ch(/* Dim */0, param);
          }), separator);
    return add_ch(/* NoColor */3, /* ' ' */32);
  };
  List.iter((function (param) {
          var gutter = param.gutter;
          if (gutter) {
            var line_number = gutter._0;
            return List.iteri((function (i, line) {
                          var gutter_content = i === 0 ? String(line_number) : "";
                          var gutter_color = i === 0 && line_number >= highlight_line_start_line && line_number <= highlight_line_end_line ? (
                              is_warning ? /* Warn */2 : /* Err */1
                            ) : /* NoColor */3;
                          draw_gutter(gutter_color, gutter_content);
                          $$String.iteri((function (ii, ch) {
                                  var c = ii >= line.start && ii < line.end_ ? (
                                      is_warning ? /* Warn */2 : /* Err */1
                                    ) : /* NoColor */3;
                                  return add_ch(c, ch);
                                }), line.s);
                          return add_ch(/* NoColor */3, /* '\n' */10);
                        }), param.content);
          }
          draw_gutter(/* Dim */0, ".");
          add_ch(/* Dim */0, /* '.' */46);
          add_ch(/* Dim */0, /* '.' */46);
          add_ch(/* Dim */0, /* '.' */46);
          return add_ch(/* NoColor */3, /* '\n' */10);
        }), stripped_lines);
  return $$Buffer.contents(buf);
}

var Super_code_frame = {
  digits_count: digits_count,
  seek_2_lines_before: seek_2_lines_before,
  seek_2_lines_after: seek_2_lines_after,
  leading_space_count: leading_space_count,
  break_long_line: break_long_line,
  filter_mapi: filter_mapi,
  Color: Color,
  setup: setup,
  print: print
};

function print$1(message_kind, intro, src, ppf, loc) {
  if (message_kind === "warning_as_error") {
    Curry._2(Format.fprintf(ppf), "@[@{<error>%s@} (configured as error) @]@,", intro);
  } else if (message_kind === "warning") {
    Curry._2(Format.fprintf(ppf), "@[@{<info>%s@}@]@,", intro);
  } else {
    Curry._2(Format.fprintf(ppf), "@[@{<error>%s@}@]@,", intro);
  }
  var match = $$Location.get_pos_info(loc.loc_start);
  var start_char = match[2];
  var start_line = match[1];
  var match$1 = $$Location.get_pos_info(loc.loc_end);
  var end_char = match$1[2];
  var end_line = match$1[1];
  var normalizedRange;
  if (start_char === -1 || end_char === -1) {
    normalizedRange = undefined;
  } else if (start_line === end_line && start_char >= end_char) {
    var same_char = start_char + 1 | 0;
    normalizedRange = [
      [
        start_line,
        same_char
      ],
      [
        end_line,
        same_char
      ]
    ];
  } else {
    normalizedRange = [
      [
        start_line,
        start_char + 1 | 0
      ],
      [
        end_line,
        end_char
      ]
    ];
  }
  if (normalizedRange === undefined) {
    return ;
  }
  try {
    return Curry._2(Format.fprintf(ppf), "@,%s", print(message_kind === "warning", src, loc.loc_start, loc.loc_end));
  }
  catch (raw_exn){
    var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
    if (exn.RE_EXN_ID === P.Sys_error) {
      return ;
    }
    throw exn;
  }
}

function super_error_reporter(ppf, src, param) {
  return Curry._4(Format.fprintf(ppf), "@[<v>@,  %a@,  %s@,@]", (function (param, param$1) {
                return print$1("error", "Syntax error!", src, param, param$1);
              }), param.loc, param.msg);
}

var Super_location = {
  fprintf: Format.fprintf,
  print_filename: $$Location.print_filename,
  print: print$1,
  super_error_reporter: super_error_reporter
};

export {
  Super_code_frame ,
  Super_location ,
  
}
/* P Not a pure module */
