
############################################################################################################
njs_path                  = require 'path'
#...........................................................................................................
TRM                       = require 'coffeenode-trm'
rpr                       = TRM.rpr.bind TRM
badge                     = 'ansi256'
log                       = TRM.get_logger 'plain', badge
info                      = TRM.get_logger 'info',  badge
alert                     = TRM.get_logger 'alert', badge
debug                     = TRM.get_logger 'debug', badge
warn                      = TRM.get_logger 'warn',  badge
help                      = TRM.get_logger 'help',  badge

#-----------------------------------------------------------------------------------------------------------
rgb_hex_by_vt100_colorcode =
  # Primary 3-bit 8 colors. Unique representation!
  '0':    '000000'
  '1':    '800000'
  '2':    '008000'
  '3':    '808000'
  '4':    '000080'
  '5':    '800080'
  '6':    '008080'
  '7':    'c0c0c0'
  # Equivalent "bright" versions of original 8 colors.
  '8':    '808080'
  '9':    'ff0000'
  '10':   '00ff00'
  '11':   'ffff00'
  '12':   '0000ff'
  '13':   'ff00ff'
  '14':   '00ffff'
  '15':   'ffffff'
  # Strictly ascending.
  '16':   '000000'
  '17':   '00005f'
  '18':   '000087'
  '19':   '0000af'
  '20':   '0000d7'
  '21':   '0000ff'
  '22':   '005f00'
  '23':   '005f5f'
  '24':   '005f87'
  '25':   '005faf'
  '26':   '005fd7'
  '27':   '005fff'
  '28':   '008700'
  '29':   '00875f'
  '30':   '008787'
  '31':   '0087af'
  '32':   '0087d7'
  '33':   '0087ff'
  '34':   '00af00'
  '35':   '00af5f'
  '36':   '00af87'
  '37':   '00afaf'
  '38':   '00afd7'
  '39':   '00afff'
  '40':   '00d700'
  '41':   '00d75f'
  '42':   '00d787'
  '43':   '00d7af'
  '44':   '00d7d7'
  '45':   '00d7ff'
  '46':   '00ff00'
  '47':   '00ff5f'
  '48':   '00ff87'
  '49':   '00ffaf'
  '50':   '00ffd7'
  '51':   '00ffff'
  '52':   '5f0000'
  '53':   '5f005f'
  '54':   '5f0087'
  '55':   '5f00af'
  '56':   '5f00d7'
  '57':   '5f00ff'
  '58':   '5f5f00'
  '59':   '5f5f5f'
  '60':   '5f5f87'
  '61':   '5f5faf'
  '62':   '5f5fd7'
  '63':   '5f5fff'
  '64':   '5f8700'
  '65':   '5f875f'
  '66':   '5f8787'
  '67':   '5f87af'
  '68':   '5f87d7'
  '69':   '5f87ff'
  '70':   '5faf00'
  '71':   '5faf5f'
  '72':   '5faf87'
  '73':   '5fafaf'
  '74':   '5fafd7'
  '75':   '5fafff'
  '76':   '5fd700'
  '77':   '5fd75f'
  '78':   '5fd787'
  '79':   '5fd7af'
  '80':   '5fd7d7'
  '81':   '5fd7ff'
  '82':   '5fff00'
  '83':   '5fff5f'
  '84':   '5fff87'
  '85':   '5fffaf'
  '86':   '5fffd7'
  '87':   '5fffff'
  '88':   '870000'
  '89':   '87005f'
  '90':   '870087'
  '91':   '8700af'
  '92':   '8700d7'
  '93':   '8700ff'
  '94':   '875f00'
  '95':   '875f5f'
  '96':   '875f87'
  '97':   '875faf'
  '98':   '875fd7'
  '99':   '875fff'
  '100':  '878700'
  '101':  '87875f'
  '102':  '878787'
  '103':  '8787af'
  '104':  '8787d7'
  '105':  '8787ff'
  '106':  '87af00'
  '107':  '87af5f'
  '108':  '87af87'
  '109':  '87afaf'
  '110':  '87afd7'
  '111':  '87afff'
  '112':  '87d700'
  '113':  '87d75f'
  '114':  '87d787'
  '115':  '87d7af'
  '116':  '87d7d7'
  '117':  '87d7ff'
  '118':  '87ff00'
  '119':  '87ff5f'
  '120':  '87ff87'
  '121':  '87ffaf'
  '122':  '87ffd7'
  '123':  '87ffff'
  '124':  'af0000'
  '125':  'af005f'
  '126':  'af0087'
  '127':  'af00af'
  '128':  'af00d7'
  '129':  'af00ff'
  '130':  'af5f00'
  '131':  'af5f5f'
  '132':  'af5f87'
  '133':  'af5faf'
  '134':  'af5fd7'
  '135':  'af5fff'
  '136':  'af8700'
  '137':  'af875f'
  '138':  'af8787'
  '139':  'af87af'
  '140':  'af87d7'
  '141':  'af87ff'
  '142':  'afaf00'
  '143':  'afaf5f'
  '144':  'afaf87'
  '145':  'afafaf'
  '146':  'afafd7'
  '147':  'afafff'
  '148':  'afd700'
  '149':  'afd75f'
  '150':  'afd787'
  '151':  'afd7af'
  '152':  'afd7d7'
  '153':  'afd7ff'
  '154':  'afff00'
  '155':  'afff5f'
  '156':  'afff87'
  '157':  'afffaf'
  '158':  'afffd7'
  '159':  'afffff'
  '160':  'd70000'
  '161':  'd7005f'
  '162':  'd70087'
  '163':  'd700af'
  '164':  'd700d7'
  '165':  'd700ff'
  '166':  'd75f00'
  '167':  'd75f5f'
  '168':  'd75f87'
  '169':  'd75faf'
  '170':  'd75fd7'
  '171':  'd75fff'
  '172':  'd78700'
  '173':  'd7875f'
  '174':  'd78787'
  '175':  'd787af'
  '176':  'd787d7'
  '177':  'd787ff'
  '178':  'd7af00'
  '179':  'd7af5f'
  '180':  'd7af87'
  '181':  'd7afaf'
  '182':  'd7afd7'
  '183':  'd7afff'
  '184':  'd7d700'
  '185':  'd7d75f'
  '186':  'd7d787'
  '187':  'd7d7af'
  '188':  'd7d7d7'
  '189':  'd7d7ff'
  '190':  'd7ff00'
  '191':  'd7ff5f'
  '192':  'd7ff87'
  '193':  'd7ffaf'
  '194':  'd7ffd7'
  '195':  'd7ffff'
  '196':  'ff0000'
  '197':  'ff005f'
  '198':  'ff0087'
  '199':  'ff00af'
  '200':  'ff00d7'
  '201':  'ff00ff'
  '202':  'ff5f00'
  '203':  'ff5f5f'
  '204':  'ff5f87'
  '205':  'ff5faf'
  '206':  'ff5fd7'
  '207':  'ff5fff'
  '208':  'ff8700'
  '209':  'ff875f'
  '210':  'ff8787'
  '211':  'ff87af'
  '212':  'ff87d7'
  '213':  'ff87ff'
  '214':  'ffaf00'
  '215':  'ffaf5f'
  '216':  'ffaf87'
  '217':  'ffafaf'
  '218':  'ffafd7'
  '219':  'ffafff'
  '220':  'ffd700'
  '221':  'ffd75f'
  '222':  'ffd787'
  '223':  'ffd7af'
  '224':  'ffd7d7'
  '225':  'ffd7ff'
  '226':  'ffff00'
  '227':  'ffff5f'
  '228':  'ffff87'
  '229':  'ffffaf'
  '230':  'ffffd7'
  '231':  'ffffff'
  # Gray-scale range
  '232':  '080808'
  '233':  '121212'
  '234':  '1c1c1c'
  '235':  '262626'
  '236':  '303030'
  '237':  '3a3a3a'
  '238':  '444444'
  '239':  '4e4e4e'
  '240':  '585858'
  '241':  '626262'
  '242':  '6c6c6c'
  '243':  '767676'
  '244':  '808080'
  '245':  '8a8a8a'
  '246':  '949494'
  '247':  '9e9e9e'
  '248':  'a8a8a8'
  '249':  'b2b2b2'
  '250':  'bcbcbc'
  '251':  'c6c6c6'
  '252':  'd0d0d0'
  '253':  'dadada'
  '254':  'e4e4e4'
  '255':  'eeeeee'


#-----------------------------------------------------------------------------------------------------------
ansi_vt100_cc_matcher = /(?:\x1b\x5b)([\?=;0-9]*?)([ABCDHJKfhlmnpsu])/g

#-----------------------------------------------------------------------------------------------------------
@analyze = ( text ) ->
  ### Parse ANSI control codes out of `text` and return a list of alternating text / opcode chunks; the
  first element of the list and all elements with even indexes will represent (possibly empty) literal
  texts, while elements with even indexes will be sub-lists representing control codes. Each control
  code looks like `[ 'm', 38, 5, 199 ]` or `[ 'm', 0 ]`, with the opcode letter coming first, followed
  by the integer parameters.

  Adapted from https://github.com/atdt/escapes.js/blob/master/escapes.js ###
  R = []
  #.........................................................................................................
  loop
    position  = ansi_vt100_cc_matcher.lastIndex
    match     = ansi_vt100_cc_matcher.exec text
    if match isnt null
      R.push text.slice position, match.index
      parameters  = [ match[ 2 ], ]
      parameters.push parseInt x, 10 for x in match[ 1 ].split ';'
      R.push parameters
    break if ansi_vt100_cc_matcher.lastIndex is 0
  #.........................................................................................................
  R.push text.slice position if position < text.length
  return R

#-----------------------------------------------------------------------------------------------------------
@as_html = ( text, options ) ->
  return ( @_as_html text, options ).join ''

#-----------------------------------------------------------------------------------------------------------
@_as_html = ( text, options ) ->
  is_ansicode     = yes
  R               = []
  open_span_count = 0
  css_prefix      = if options? and options[ 'css-prefix' ]? then options[ 'css-prefix' ] else 'ansi'
  vt100_reset     = css_prefix.concat '-m-0'
  vt100_clear     = css_prefix.concat '-K'
  #.........................................................................................................
  for chunk in @analyze text
    is_ansicode = not is_ansicode
    if is_ansicode
      css_class = css_prefix.concat '-', chunk.join '-'
      if css_class is vt100_reset or css_class is vt100_clear
        R.push '</span>'
        open_span_count -= 1
      else
        R.push "<span class='#{css_class}'>"
        open_span_count += 1
      continue
    else
      ### TAINT must escape ###
      R.push chunk
  #.........................................................................................................
  if open_span_count > 0 and ( options? and options[ 'close-spans' ] )
    R.push '</span>' for n in [ 0 ... open_span_count ]
  #.........................................................................................................
  return R

#-----------------------------------------------------------------------------------------------------------
@get_css_source = ( options ) ->
  R           = []
  css_prefix  = if options? and options[ 'css-prefix' ]? then options[ 'css-prefix' ] else 'ansi'
  for color_code, rgb_hex of rgb_hex_by_vt100_colorcode
    R.push ".#{css_prefix}-m-38-5-#{color_code} { color: #{rgb_hex}; }"
  #.........................................................................................................
  return R.join '\n'




############################################################################################################
colortext     = TRM.pen 'foo', ( TRM.steel 'helo', 42 ), 'bar', ( TRM.pink 'baz' )
console.log colortext
# color_matcher = /\x1b\[(38);(05);([0-9]{1,3})m([^\x1b]*)\x1b\[(?:0m|K)/
# console.log rpr colortext.match color_matcher

# info rpr TRM.pen ( TRM.pink 'helo' ), 'foo', ( TRM.gold 'oops' )

colortext = '\x1b[38;05;199mhelo\x1b[0m foo \x1b[38;05;214moops\x1b[0m'
colortext = '\x1b[38;05;199mhelo\x1b[0m foo \x1b[38;05;214moops'

info @analyze colortext
info @as_html colortext
info @as_html colortext, 'css-prefix': 'xxxx', 'close-spans': yes
debug @get_css_source()


# console.log colortext.split /\x1b/

# recolorize = ( text ) ->
#   parts         = text.split /\x1b/
#   is_colorized  = no
#   R             = []
#   for  in parts
#     if is_colorized
#       null

