#!/bin/sh
#
# tarcpj <cpj file>
#
# 2007-05-14: Fix problem with stripping workspace from .cpj
# 2009-10-08: Fix problem with handling non-inlined TARGET_ANIM
# 2010-04-29: Now handles INCLUDE files in models, mappings, and scalings.
# 2014-12-17: Updated to use GIANT_DATA_DIR in addition to BIO_DATA_DIR
# 2019-03-25: Fixed a bug handling .cpj files with inlined target anims.
# 2021-11-05: Fixed a bug handling .cpj files with inlined anims containing
#             ASF and AMC files
# 2022-03-04: Now includes CURVE_DEFORMER files.
# 2024-07-22: Now includes ADDITIONAL_SKIN files.
#

if [ $# = 0 ]; then
  echo "" >&2
  echo "Usage: tarcpj <cpj file>" >&2
  echo "  Creates a .tar.gz file for the given charmapper project." >&2
  echo "" >&2
  echo "Usage: tarcpj -l <cpj file>" >&2
  echo "  Lists all the files related to the given charmapper project." >&2
  echo "" >&2
  echo "Usage: tarcpj -t <cpj file>" >&2
  echo "  Lists the files directly referenced by the charmapper project." >&2
  echo "" >&2
  exit 1
fi

list_only=0
top_only=0

if [ $# -gt 1 -a $1 = "-l" ]; then
  list_only=1
  shift
fi


if [ $# -gt 1 -a $1 = "-t" ]; then
  top_only=1
  shift
fi

# platform check

uname_out=`uname`
if [ `expr $uname_out : 'IRIX'` = 4 ]; then
  AWK=nawk
elif [ "$uname_out" = "Linux" ]; then
  AWK=awk
else
  echo "Unknown platform." >&2
  exit 1
fi

data_dir=${GIANT_DATA_DIR%/}

if [ "$data_dir" = "" ]; then
  data_dir=${BIO_DATA_DIR%/}
fi

cpj_file=$1

if [ ! -f "$cpj_file" ]; then
  echo >&2
  echo "No such file: $cpj_file" >&2
  echo >&2
  exit 1
fi

fixup_fn() {
  orig_fn=$1
  fn=${1#$data_dir//}          # remove the substring equal to the workspace
                              # path
  fn=${fn#$data_dir/}          # remove the substring equal to the workspace
                              # path
  fn=${fn#'$BIO_DATA_DIR'/}   # remove the string "$BIO_DATA_DIR/"
  fn=${fn#'$GIANT_DATA_DIR'/} # remove the string "$GIANT_DATA_DIR/"
  fn=${fn#'$NU_DATA_DIR'/}    # remove the string "$NU_DATA_DIR/"

  if [ ! -f "$fn" ] ; then
    if [ ! -f "$fn.gz" ]; then
      echo "Missing file '$fn'" 1>&2
      echo ""                 # doesnt exist, returning empty string
    else
      echo "$fn.gz"
    fi
  else
    echo $fn
  fi
}

full_path_name() {  # must be an easier way to do this
  cwd=`pwd`
  dn=`dirname $1`
  cd $dn
  dir=`/bin/pwd`
  cd $cwd
  echo $dir/`basename $1`
}

get_includes() {
# recursively finds include files in the given file using the tagfile utility
# this does not handle infinite recursion currently
# handles compressed files
  base_file=$1
  base_file=`eval echo $base_file`

  if [ x"$base_file" != x"" -a ! -f "$base_file" ]; then
    # choose the compressed version of the file if it exists and the
    # uncompressed doesn't exist
    if [ -f "${base_file}.gz" ]; then
      base_file="${base_file}.gz"
    fi
  fi

  if [ x"$base_file" != x"" -a -f "$base_file" ]; then
    uncompressed_base_file=${base_file%.gz}

    if [ $uncompressed_base_file != $base_file ]; then
      tmp_uncompressed_base_file=${uncompressed_base_file}.tarprj_$$
      gunzip -c $base_file >$tmp_uncompressed_base_file
      tagfile_file=$tmp_uncompressed_base_file
    else
      tagfile_file=$base_file
    fi

    include_file_names=`tagfile -getfile INCLUDE.FILE_NAME $tagfile_file`

    if [ x"$include_file_names" != x"" ]; then
      # pass the result through xargs to join the output into one line
      echo "$include_file_names" | expand_includes | xargs
    fi

    if [ "$uncompressed_base_file" != "$base_file" ]; then
      rm -f $tmp_uncompressed_base_file
    fi
  fi
}


topcpjfiles () {
  cpj="$1"
  awk '
    function expand(x)
    {
      gsub("\\$BIO_DATA_DIR/","",x);
      gsub("\\$GIANT_DATA_DIR/","",x);
      gsub("\\$NU_DATA_DIR/","",x);
      return x;
    }

    $1=="CURVE_DEFORMER" { in_curve_deformer = 1 }
    $1=="}" { in_curve_deformer = 0 }
    $1=="FILE_NAME:" && in_curve_deformer { print "FILE: "expand($2) }
    $1=="MODEL:" && $2!="[camera]" { print "MODEL: "expand($2) }
    $1=="MAPPING:" && $2!="[camera]" { print "MAPPING: "expand($2) }
    $1=="MOTION:" { print "MOTION: "expand($2) }
    $1=="SCALING:" { print "SCALING: "expand($2) }
    $1=="ASF:" { print "ASF: "expand($2) }
    $1=="AMC:" { print "AMC: "expand($2) }
    $1=="PATH:" { print "FILE: "expand($2) }
  ' <"$cpj"
}


expand_includes() {
  while read include_file_name; do
    echo "$include_file_name"
    get_includes "$include_file_name"
  done
}


if [ $top_only = 1 ]; then
  topcpjfiles "$cpj_file"
  exit
fi


cpj_file=`full_path_name $cpj_file`

models=`
  $AWK '
    $1=="MODEL:" { print $2 }
  ' <$cpj_file
`

models=`echo $models | xargs -n 1 | expand_includes | xargs`

asfs=`
  $AWK '
    $1=="ASF:" { print $2 }
  ' <$cpj_file
`

objs=$(
  $AWK '
    $1=="PATH:" { print $2 }
  ' <$cpj_file
)

cdfs=`
  $AWK '
    $1=="CURVE_DEFORMER" { in_curve_deformer = 1 }
    $1=="}" { in_curve_deformer = 0 }
    $1=="FILE_NAME:" && in_curve_deformer { print $2 }
  ' <$cpj_file
`

mappings=`
  $AWK '
    $1=="MAPPING:" { print $2 }
  ' <$cpj_file
`

mappings=`echo $mappings | xargs -n 1 | expand_includes | xargs`

motions=`
  $AWK '
    $1=="MOTION:" { print $2 }
  ' <$cpj_file
`

amcs=`
  $AWK '
    $1=="AMC:" { print $2 }
  ' <$cpj_file
`

scalings=`
  $AWK '
    $1=="SCALING:" { print $2 }
  ' <$cpj_file
`

scalings=`echo $scalings | xargs -n 1 | expand_includes | xargs`

# Make it so that the command can be executed from any directory
# we have to create the tar file as if we are in the workspace
# so it will extract properly when extracted to the workspace.

cwd=`pwd`
cd $data_dir
tar_file=$cwd/`basename $cpj_file`.tar.gz

target_model=`tagfile -getfile TARGET_ANIM.MODEL $cpj_file`

if [ "$target_model" = "" ]; then
  target_asf=`tagfile -getfile TARGET_ANIM.ASF $cpj_file`

  if [ "$target_asf" != "" ]; then
    target_asf=`fixup_fn $target_asf`
    target_anim_files=`echo $target_asf`
    target_amc=`tagfile -getfile TARGET_ANIM.AMC $cpj_file`
    if [ "$target_amc" != "" ]; then
      target_amc=`fixup_fn $target_amc`
      target_anim_files="$target_anim_files `echo $target_amc`"
    fi
  else
    target_anim=`tagfile -getfile TARGET_ANIM $cpj_file`
    target_anim_files=""

    if [ x"$target_anim" != x ]; then
      target_anim=`fixup_fn $target_anim`
      target_anim_files=`(
	echo $target_anim
	taranim -l "$target_anim"
      )`
    fi
  fi

else
  target_mapping=`tagfile -getfile TARGET_ANIM.MAPPING $cpj_file`
  target_motion=`tagfile -getfile TARGET_ANIM.MOTION $cpj_file`
  target_scaling=`tagfile -getfile TARGET_ANIM.SCALING $cpj_file`

  for file in $target_model $target_mapping $target_motion $target_scaling; do
    fixed_target_anim_files="$fixed_target_anim_files `fixup_fn $file`"
  done
  target_anim_files=$fixed_target_anim_files
fi

# Process the file names so they tar up nicely relative to the workspace.
# Set the file names to nothing if they do not exist.

cpj_file=`fixup_fn $cpj_file`

new_models=""

for file in $models; do
  if [ x"$file" != "[camera]" ]; then
    model=`fixup_fn "$file"`
    mdl_textures=`awk '
      $1=="TEXTURE" { in_texture=1; }
      in_texture && $1=="NAME:" { print $2; }
      $1=="}" { in_texture=0; }
    ' <$model`
    textures="$textures $mdl_textures"
    new_models="$new_models $model"
  fi
done

models=$new_models
new_textures=""
for file in $textures; do
  new_textures="$new_textures `fixup_fn $file`"
done
textures=$new_textures

for file in $asfs; do
  new_asfs="$new_asfs `fixup_fn $file`"
done

asfs=$new_asfs

objs=$(
  echo $objs
  for asf in $asfs; do
    asf=$(eval echo $asf)
    $AWK '
      $1=="path" {
        gsub("\"","",$2)
        print $2
      }
    ' <$asf
  done
)

new_objs=""


for file in $objs; do
  new_objs="$new_objs `fixup_fn $file`"
done

objs=$new_objs

new_cdfs=""

for file in $cdfs; do
  new_cdfs="$new_cdfs `fixup_fn $file`"
done

cdfs=$new_cdfs

for file in $mappings; do
  if [ $file != "[camera]" ]; then
    new_mappings="$new_mappings `fixup_fn $file`"
  fi
done

mappings=$new_mappings

for file in $motions; do
  new_motions="$new_motions `fixup_fn $file`"
done

motions=$new_motions

for file in $amcs; do
  new_amcs="$new_amcs `fixup_fn $file`"
done

amcs=$new_amcs

for file in $scalings; do
  new_scalings="$new_scalings `fixup_fn $file`"
done

scalings=$new_scalings

# do the tar command
files="$cpj_file $target_anim $target_anim_files $models $mappings $motions $scalings $asfs $amcs $objs $cdfs"

files=`echo $files | xargs -n 1 | sort | uniq`

if [ $list_only = 1 ]; then
  echo "$files"
else
  tar zcvf $tar_file $files
  echo >&2
  echo "Created $tar_file" >&2
  echo >&2
fi
