#!/bin/bash
test -s ./j-dim.conf || {
  echo "no configuration found, writing a default to 'j-dim.conf'"
  cat > ./j-dim.conf << EOF
# default configuration generated by 'j-dim.sh'
# =============================================
#
# 'level' means the corresponding size is 2^level
#
# basic configuration
# -------------------
#
# minimum size of Julia sets
#
minjlevel=5
#
# maximum size of Julia sets
#
maxjlevel=8
#
# minimum size of image plane
#
minmlevel=5
#
# maximum size of image plane
#
maxmlevel=8
#
# size of image plane for Julia set map
#
juliamlevel=4
#
# size of Julia sets for Julia set map
#
juliajlevel=8
#
# pixel size of thumbnails
#
thumb=64
#
# advanced configuration
# ----------------------
#
# undocumented so far...
#
doout=1
dosum=1
minsum=10
maxsum=16
dopause=0
dosrc=1
dokey=1
dojulia=1
dorender=1
docolour=1
dowebpage=1
dolessdetails=1
dolesspnglinks=1
doarchive=1
#
# eof
EOF
  echo "now edit 'j-dim.conf' to suit your needs and re-run 'j-dim.sh'"
  exit
}

source ./j-dim.conf

if (( doout ))
then
  out="OUT-$(date --iso=s | tr 'T:+' '---')"
else
  out="${1}"
fi
mkdir -p "${out}"
pushd "${out}"
if (( dopause ))
then
  echo "press enter to continue..."
  read line
  echo "...continuing"
fi
mkdir -p j-dim
#
(
  echo "{ j-dim-render {"

  if (( dosrc ))
  then
    echo "{ j-dim-src {"
    mkdir -p j-dim/src
    cp -at j-dim/src ../j-dim-render.c ../j-dim-colour.c ../j-dim-colour-key.c ../j-dim.sh
    gcc -std=c99 -Wall -Wextra -pedantic -O3 -fopenmp -o j-dim-render j-dim/src/j-dim-render.c -lGLEW -lglfw
    gcc -std=c99 -Wall -Wextra -pedantic -O3 -fopenmp -o j-dim-colour j-dim/src/j-dim-colour.c -lm
    gcc -std=c99 -Wall -Wextra -pedantic -O3 -fopenmp -o j-dim-colour-key j-dim/src/j-dim-colour-key.c -lm
    echo "} j-dim-src }"
  fi

  if (( dokey ))
  then
    echo "{ j-dim-key {"
    ./j-dim-colour-key
    mkdir -p j-dim/key
    for key in $(seq 0 7)
    do
      pnmtopng -force -compression 9 < "j-dim-key-${key}.ppm" > "j-dim/key/${key}.png"
    done
    echo "} j-dim-key }"
  fi

  if (( dojulia ))
  then
    echo "{ j-dim-julia {"
    ./j-dim-render "${juliamlevel}" "${juliajlevel}" julia
    mkdir -p j-dim/julia
    for j in $(seq 0 "$(((1 << (juliamlevel - 1)) - 1))")
    do
      jj="$(((1 << juliamlevel) - 1 - j))"
      for i in $(seq 0 "$(((1 << juliamlevel) - 1))")
      do
        src="j-dim-$(printf %02d "${juliamlevel}")-$(printf %02d "${juliajlevel}")-julia-$(printf %02d "${j}")-$(printf %02d "${i}")"
        pnmtopng -force -compression 9 < "${src}.ppm" > "j-dim/julia/$(printf %02d "${j}")-$(printf %02d "${i}").png"
        pnmscale -xysize "${thumb}" "${thumb}" < "${src}.ppm" | pnmtojpeg --optimize > "j-dim/julia/$(printf %02d "${j}")-$(printf %02d "${i}").jpg"
        pnmflip -tb < "${src}.ppm" | pnmtopng -force -compression 9 > "j-dim/julia/$(printf %02d "${jj}")-$(printf %02d "${i}").png"
        pnmscale -xysize "${thumb}" "${thumb}" < "${src}.ppm" | pnmflip -tb | pnmtojpeg --optimize > "j-dim/julia/$(printf %02d "${jj}")-$(printf %02d "${i}").jpg"
      done
    done
    echo "} j-dim-julia }"
  fi

  if (( dosum ))
  then
    minsum="$(( minjlevel + minmlevel ))"
    maxsum="$(( maxjlevel + maxmlevel ))"
  fi
  for sum in $(seq $(( minsum )) $(( maxsum )))
  do
    for jlevel in $(seq $((minjlevel)) $((sum - minmlevel)))
    do
      if (( minjlevel <= jlevel && jlevel <= maxjlevel ))
      then
        mlevel=$((sum - jlevel))
        if (( minmlevel <= mlevel && mlevel <= maxmlevel ))
        then
          if (( dorender ))
          then
            ./j-dim-render "${mlevel}" "${jlevel}"
          fi
          if (( docolour ))
          then
            (
              stem="j-dim-$(printf %02d ${mlevel})-$(printf %02d ${jlevel})"
              dir="j-dim/$(printf %02d ${mlevel})/$(printf %02d ${jlevel})"
              mkdir -p "${dir}"
              ./j-dim-colour "${mlevel}" "${jlevel}"
              for l0 in $(seq 0 $((jlevel - 1)))
              do
                for l1 in $(seq $((l0 + 1)) $((jlevel)))
                do
                  src="${stem}-$(printf %02d ${l0})-$(printf %02d ${l1})"
                  dst="${dir}/$(printf %02d ${l0})-$(printf %02d ${l1})"
                  pnmtopng -force -compression 9 < "${src}.ppm" > "${dst}.png" 
                  pnmscale -xysize "${thumb}" "${thumb}" < "${src}.ppm" | pnmtojpeg --optimize > "${dst}.jpg"
                done
              done
            ) 2>/dev/null &
          fi
        fi
      fi
    done
  done

  echo "} j-dim-render }"
) |
ts |
tee -a j-dim.log
#
if (( dopause ))
then
  echo "press enter to continue..."
  read line
  echo "...continuing"
fi
#
if (( dowebpage ))
then
echo "{ j-dim-webpage {" | ts
(
  cat << EOF
<html>
<head>
<title>Fractal Dimension Of Julia Sets</title>
<style type='text/css'>
th, td { border: 2px solid transparent; margin: 0; padding: 2px; }
th { text-align: center; }
td { text-align: right; }
td.best { border-color: black; }
td:hover { border-color: red; }
td.best:hover { border-color: magenta; }
a { color: black; }
a:hover { color: red; }
td a { text-decoration: none; }
table img { width: ${thumb}px; height: ${thumb}px; }
table#keytable img { width: 128px; height: 32px; }
</style>
</head>
<body>
<h1 id='top'><a href='#top'>Fractal Dimension Of Julia Sets</a></h1>
<h2 id='toc'><a href='#toc'>Contents</a></h2>
<ul>
<li><a href='#jdim'>Results</a></li>
<li><a href='#key'>Colour Key</a></li>
<li><a href='#julia'>Julia Sets</a></li>
<li><a href='#bench'>Benchmarks</a></li>
<li><a href='#source'>Source Code</a></li>
<li><a href='#results'>Detailed Results</a></li>
</ul>
<h2 id='jdim'><a href='#jdim'>Results</a></h2>
<p><img src='$(printf %02d "${maxmlevel}")/$(printf %02d "${maxjlevel}")/$(printf %02d "$((maxjlevel - 3))")-$(printf %02d "$((maxjlevel - 1))").png' /></p>
<h2 id='key'><a href='#key'>Colour Key</a></h2>
<table id='keytable'><tr>
<th>0.00</th><td><img src='key/0.png' /></td>
<th>0.25</th><td><img src='key/1.png' /></td>
<th>0.50</th><td><img src='key/2.png' /></td>
<th>0.75</th><td><img src='key/3.png' /></td>
<th>1.00</th><td><img src='key/4.png' /></td>
<th>1.25</th><td><img src='key/5.png' /></td>
<th>1.50</th><td><img src='key/6.png' /></td>
<th>1.75</th><td><img src='key/7.png' /></td>
<th>2.00</th>
</tr></table>
<h2 id='julia'><a href='#julia'>Julia Sets</a></h2>
<table>
<tr>
<th>Im&nbsp;\\&nbsp;Re</th>
EOF
  log="j-dim-$(printf %02d "${juliamlevel}")-$(printf %02d "${juliajlevel}").log"
  cat "${log}" |
  grep "^j =    0" |
  while read line
  do
    re="${line:26:6}"
    echo "<th>${re}</th>"
  done
  echo "<th>Re&nbsp;/&nbsp;Im</th>"
  echo "</tr>"
  cat "${log}" |
  while read line
  do
    j="${line:4:4}"
    i="${line:15:4}"
    re="${line:26:6}"
    im="${line:36:5}"
    dim="${line:77}"
    if (( i == 0 ))
    then
      echo "<tr>"
      echo "<th>+${im}</th>"
    fi
    stem="julia/$(printf %02d "$((j))")-$(printf %02d "$((i))")"
    echo "<td><a href='${stem}.png' title='dim=${dim}'><img src='${stem}.jpg' /></a></td>"
    if (( i == (1 << juliamlevel) - 1 ))
    then
      echo "<th>+${im}</th>"
      echo "</tr>"
    fi
  done
  for j in $(seq $(((1 << juliamlevel) - 1)) -1 0)
  do
    cat "${log}" |
    grep "^j = $(printf %4d "${j}")" |
    while read line
    do
      i="${line:15:4}"
      re="${line:26:6}"
      im="${line:36:5}"
      dim="${line:77}"
      if (( i == 0 ))
      then
        echo "<tr>"
        echo "<th>-${im}</th>"
      fi
      stem="julia/$(printf %02d "$(((1 << juliamlevel) - 1 - j))")-$(printf %02d "$((i))")"
      echo "<td><a href='${stem}.png' title='dim = ${dim}'><img src='${stem}.jpg' /></a></td>"
      if (( i == (1 << juliamlevel) - 1 ))
      then
        echo "<th>-${im}</th>"
        echo "</tr>"
      fi
    done
  done
  echo "<tr>"
  echo "<th>Im&nbsp;/&nbsp;Re</th>"
  cat "${log}" |
  grep "^j =    0" |
  while read line
  do
    re="${line:26:6}"
    echo "<th>${re}</th>"
  done
  echo "<th>Re&nbsp;\\&nbsp;Im</th>"
  echo "</tr>"
  echo "</table>"

  cat << EOF
<h2 id='bench'><a href='#bench'>Benchmarks</a></h2>
<p>Timings are in seconds, wall-clock elapsed time.</p>
<table>
<tr>
<th colspan='2' rowspan='2'></th>
<th colspan='$(( maxjlevel - minjlevel + 1 ))'>Julia</th>
</tr>
<tr>
EOF
  for jlevel in $(seq "${maxjlevel}" -1 "${minjlevel}")
  do
    echo "<th>$((1 << jlevel))<sup>2</sup></th>"
  done
  echo "</tr>"
  echo "<tr>"
  echo "<th rowspan='$(( maxmlevel - minmlevel + 1))'>Image</th>"
  for mlevel in $(seq "${maxmlevel}" -1 "${minmlevel}")
  do
    if (( mlevel < maxmlevel ))
    then
      echo "<tr>"
    fi
    echo "<th>$((1 << mlevel))<sup>2</sup></th>"
    for jlevel in $(seq "${maxjlevel}" -1 "${minjlevel}")
    do
      needle="j-dim-$(printf %02d "${mlevel}")-$(printf %02d "${jlevel}")"
      cat j-dim.log |
      grep "${needle}" |
      tail -n 2 |
      ts -r %s |
      (
        read start rest &&
        read end rest &&
        echo "<td>$((end - start))</td>"
      ) || echo "<td>?</td>"
    done
    echo "</tr>"
  done
  echo "</table>"

  cat << EOF
<h2 id='source'><a href='#source'>Source Code</a></h2>
<dl>
<dt><a href='src/j-dim-render.c'>j-dim-render.c</a></dt>
<dd>Renders Julia sets and performs box-counting on GPU (using OpenGL 4).</dd>
<dt><a href='src/j-dim-colour.c'>j-dim-colour.c</a></dt>
<dd>Colours the raw box-counting data into various images.</dd>
<dt><a href='src/j-dim-colour-key.c'>j-dim-colour-key.c</a></dt>
<dd>Generates the images for the colour key.</dd>
<dt><a href='src/j-dim.sh'>j-dim.sh</a></dt>
<dd>Driver script that renders everything and generates this web page.</dd>
</dl>
EOF
  if (( dolessdetails ))
  then
    minmlevel="$((maxmlevel))"
  fi
  cat << EOF
<h2 id='results'><a href='#results'>Detailed Results</a></h2>
<h3 id='resultstoc'><a href='#resultstoc'>Contents</a></h3>
<table>
<tr>
<th colspan='2' rowspan='2'></th>
<th colspan='$(( maxjlevel - minjlevel + 1 ))'>Julia</th>
</tr>
<tr>
EOF
  for jlevel in $(seq "${maxjlevel}" -1 "${minjlevel}")
  do
    echo "<th>$((1 << jlevel))<sup>2</sup></th>"
  done
  echo "</tr>"
  echo "<tr>"
  echo "<th rowspan='$(( maxmlevel - minmlevel + 1))'>Image</th>"
  for mlevel in $(seq "${maxmlevel}" -1 "${minmlevel}")
  do
    if (( mlevel < maxmlevel ))
    then
      echo "<tr>"
    fi
    echo "<th>$((1 << mlevel))<sup>2</sup></th>"
    for jlevel in $(seq "${maxjlevel}" -1 "${minjlevel}")
    do
      stem="$(printf %02d ${mlevel})/$(printf %02d ${jlevel})/$(printf %02d $((jlevel - 3)))-$(printf %02d $((jlevel - 1)))"
      echo "<td><a href='#m${mlevel}j${jlevel}'><img src='${stem}.jpg' /></a></td>"
    done
    echo "</tr>"
  done
  echo "</table>"
  for mlevel in $(seq "${maxmlevel}" -1 "${minmlevel}")
  do
    for jlevel in $(seq "${maxjlevel}" -1 "${minjlevel}")
    do
      echo "<h3 id='m${mlevel}j${jlevel}'><a href='#m${mlevel}j${jlevel}'>Image $((1 << mlevel))<sup>2</sup> Julia $((1 << jlevel))<sup>2</sup></a></h3>"
      echo "<table>"
      echo "<tr>"
      echo "<th>l<sub>0</sub>&nbsp;\\&nbsp;l<sub>1</sub></th>"
      for l1 in $(seq "${jlevel}" -1 1)
      do
        echo "<th>${l1}</th>"
      done
      echo "</tr>"
      for l0 in $(seq "$((jlevel - 1))" -1 0)
      do
        echo "<tr>"
        echo "<th>${l0}</th>"
        for l1 in $(seq "$((jlevel))" -1 "$((l0 + 1))")
        do
          stem="$(printf %02d ${mlevel})/$(printf %02d ${jlevel})/$(printf %02d $((l0)))-$(printf %02d $((l1)))"
          if (( l0 == jlevel - 3 && l1 == jlevel - 1 ))
          then
            class=" class='best'"
          else
            class=""
          fi
          if (( dolesspnglinks ))
          then
            if (( l0 == jlevel - 3 && l1 == jlevel - 1 ))
            then
              echo "<td${class}><a href='${stem}.png'><img src='${stem}.jpg' /></a></td>"
            else 
              echo "<td${class}><img src='${stem}.jpg' /></td>"
            fi
          else
            echo "<td${class}><a href='${stem}.png'><img src='${stem}.jpg' /></a></td>"
          fi
        done
        if (( l0 > 0 ))
        then
          echo "<td colspan='${l0}'></td>"
        fi
        echo "</tr>"
      done
      echo "</table>"
    done
  done
  echo "</body>"
  echo "</html>"
) > j-dim/index.html
echo "} j-dim-webpage }" | ts
fi

if (( doarchive ))
then
  echo "{ j-dim-archive {" | ts
  (
    result="$(printf %02d "${maxmlevel}")/$(printf %02d "${maxjlevel}")/$(printf %02d "$((maxjlevel - 3))")-$(printf %02d "$((maxjlevel - 1))")"
    find j-dim/index.html j-dim/src j-dim/key "j-dim/${result}.png" -type f
    find j-dim/julia "j-dim/$(printf %02d "${maxmlevel}")" -iname '*.jpg' -type f
    find j-dim/julia -iname '*.png' -type f
    for jlevel in $(seq "$((maxjlevel - 1))" -1 "$((minjlevel))")
    do
      image="$(printf %02d "${maxmlevel}")/$(printf %02d "${jlevel}")/$(printf %02d "$((jlevel - 3))")-$(printf %02d "$((jlevel - 1))")"
      find "j-dim/${image}.png" -type f
    done
  ) > j-dim.list
  tar --create --verbose --owner=0 --group=0 --bzip2 --file j-dim.tar.bz2 --files-from j-dim.list
  if (( dolessdetails == 0 || dolesspnglinks == 0 ))
  then
    echo "WARNING: unsupported option combination, archive probably misses images"
  fi
  echo "} j-dim-archive }" | ts
fi

#
popd
echo
echo "${out:4}"
date --iso=s | tr 'T:+' '---'
