/** @return The path of a node */
  private Path getNodePath(String nodeName) throws PipelineException {

    NodeID targetID = new NodeID(w.user, w.view, nodeName);
    NodeStatus targetStat = mclient.status(targetID);
    NodeMod targetMod = targetStat.getHeavyDetails().getWorkingVersion();
    if (targetMod == null)
      throw new PipelineException(
          "No working version of the Target Scene Node ("
              + nodeName
              + ") exists "
              + "in the ("
              + w.view
              + ") working area owned by ("
              + PackageInfo.sUser
              + ")!");

    Path targetPath;

    FileSeq fseq = targetMod.getPrimarySequence();
    String suffix = fseq.getFilePattern().getSuffix();
    if (!fseq.isSingle() || (suffix == null) || (!suffix.equals("ma") && !suffix.equals("mb")))
      throw new PipelineException("The target node (" + nodeName + ") must be a maya scene!");
    targetPath =
        new Path(PackageInfo.sProdPath, targetID.getWorkingParent() + "/" + fseq.getFile(0));

    // System.err.println("$WORKING"+nodeName+"."+suffix);
    return targetPath;
  } // end getNodePath(String)
  /**
   * Updates the asset references for a shot within Maya and then in pipeline.
   *
   * @param shotName The name of the shot being processed.
   * @param pRemoveRef The list of assets being dereferenced from the shot.
   * @param pReplaceRef The list of assets being referenced into the shot.
   * @param nameMap
   */
  private void editShotReferences(
      String shotName,
      NodeMod targetMod,
      TreeSet<String> pRemoveRef,
      TreeSet<String> pReplaceRef,
      TreeMap<String, String> nameMap)
      throws PipelineException {
    logLine("Editing shot: " + shotName);
    boolean anim = !shotName.matches(lgtPattern);

    /* writing the mel script */
    if (anim) {
      File script = null;
      try {
        script = File.createTempFile("UpdateAssetGUI.", ".mel", PackageInfo.sTempPath.toFile());
        FileCleaner.add(script);
      } // end try
      catch (IOException ex) {
        throw new PipelineException(
            "Unable to create the temporary MEL script used to collect "
                + "texture information from the Maya scene!");
      } // end catch

      try {
        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(script)));

        for (String asset : pReplaceRef) {
          String nameSpace;
          if (asset.endsWith(lr))
            nameSpace = nameMap.get(getShortName(asset.substring(0, asset.length() - 3)));
          else {
            System.err.println("This should not be happening, a hi res asset in a lo-res node.");
            continue;
            // nameSpace = nameMap.get(getShortName(asset));
          }
          out.println("print (\"referencing file: $WORKING" + asset + ".ma\");");
          out.println(
              "file -reference -namespace \"" + nameSpace + "\" \"$WORKING" + asset + ".ma\";");
        } // end for

        for (String asset : pRemoveRef) {
          out.println("print (\"dereferencing file: $WORKING" + asset + ".ma\");");
          out.println("file -rr \"$WORKING" + asset + ".ma\";");
        } // end for

        out.println("// SAVE");
        out.println("file -save;");

        out.close();
      } // end try
      catch (IOException ex) {
        throw new PipelineException(
            "Unable to write the temporary MEL script(" + script + ") used add the references!");
      } // end catch

      NodeID targetID = new NodeID(w.user, w.view, shotName);
      // NodeStatus targetStat = mclient.status(targetID);

      /* run Maya to collect the information */
      try {

        Path targetPath = getNodePath(shotName);
        ArrayList<String> args = new ArrayList<String>();
        args.add("-batch");
        args.add("-script");
        args.add(script.getPath());
        args.add("-file");
        args.add(targetPath.toOsString());

        Path wdir = new Path(PackageInfo.sProdPath.toOsString() + targetID.getWorkingParent());

        TreeMap<String, String> env =
            mclient.getToolsetEnvironment(
                w.user, w.view, targetMod.getToolset(), PackageInfo.sOsType);

        Map<String, String> nenv = env;
        String midefs = env.get("PIPELINE_MI_SHADER_PATH");
        if (midefs != null) {
          nenv = new TreeMap<String, String>(env);
          Path dpath = new Path(new Path(wdir, midefs));
          nenv.put("MI_CUSTOM_SHADER_PATH", dpath.toOsString());
        }

        String command = "maya";
        if (PackageInfo.sOsType.equals(OsType.Windows)) command += ".exe";

        SubProcessLight proc =
            new SubProcessLight("UpdateAssetGUI", command, args, env, wdir.toFile());
        try {
          proc.start();
          proc.join();
          if (!proc.wasSuccessful()) {
            throw new PipelineException(
                "Did not correctly edit the reference due to a maya error.!\n\n"
                    + proc.getStdOut()
                    + "\n\n"
                    + proc.getStdErr());
          } // end if
        } // end try
        catch (InterruptedException ex) {
          throw new PipelineException(ex);
        } // end catch
      } // end try
      catch (Exception ex) {
        throw new PipelineException(ex);
      } // end catch
    }

    /*-edit the references in pipeline once they are done in the file-*/
    BaseAction targetAction = targetMod.getAction();
    for (String asset : pReplaceRef) {
      mclient.link(
          w.user, w.view, shotName, asset, LinkPolicy.Reference, LinkRelationship.All, null);
      if (anim) {
        /*Set the namespaces*/
        String nameSpace = nameMap.get(getShortName(asset.substring(0, asset.length() - 3)));
        System.err.println(nameSpace);
        targetAction.initSourceParams(asset);
        targetAction.setSourceParamValue(asset, "PrefixName", nameSpace);
        targetMod.setAction(targetAction);
      }
    }
    w.mclient.modifyProperties(w.user, w.view, targetMod);

    for (String asset : pRemoveRef) mclient.unlink(w.user, w.view, shotName, asset);

    if (!anim) {
      System.err.println("Queuing the switchLgt node " + shotName);
      mclient.submitJobs(w.user, w.view, shotName, null);
    }
  } // end editShotReferences
  /**
   * Using a list of shots and the assets to be changed per shot, gets each shot node and modifies
   * the references as needed.
   */
  private void processNodes() throws PipelineException {
    /*each asset, its replacement and the lo-res versions*/
    for (String asset : pAssetManager.keySet()) {
      String newAsset = pAssetManager.get(asset).getNewAsset();
      String hrAsset = asset.replace(lr, "");
      String newHrAsset = newAsset.replace(lr, "");
      logLine(
          "Checking out nodes:\n\t"
              + asset
              + "\n\t"
              + hrAsset
              + "\n\t"
              + newAsset
              + "\n\t"
              + newHrAsset);

      mclient.checkOut(w.user, w.view, asset, null, over, froz);
      mclient.checkOut(w.user, w.view, newAsset, null, over, froz);
      mclient.checkOut(w.user, w.view, hrAsset, null, over, froz);
      mclient.checkOut(w.user, w.view, newHrAsset, null, over, froz);
    } // end for

    TreeMap<String, TreeSet<String>> shotBased = convertListToShotBased();
    TreeMap<String, String> nameMap = SonyConstants.getCustomNamespaces(project);
    TreeSet<String> oldRef = new TreeSet<String>();
    TreeSet<String> newRef = new TreeSet<String>();

    for (String shot : shotBased.keySet()) {
      // check out the shot

      if (shot.endsWith("anim")) mclient.checkOut(w.user, w.view, shot, null, keep, frozU);
      else {
        continue;
        // mclient.checkOut(w.user, w.view, shot, null, keep, pFroz);
      }
      logLine("Checking out: " + shot);

      NodeMod targetMod = mclient.getWorkingVersion(w.user, w.view, shot);
      if (!shot.matches(lgtPattern)) {

        if (targetMod.isActionEnabled()) {
          System.err.println("Anim node with action enabled");
          FileSeq fseq = targetMod.getPrimarySequence();
          VersionID targetID = targetMod.getWorkingID();
          TreeMap<String, VersionID> files = new TreeMap<String, VersionID>();
          files.put(fseq.getFile(0).getPath(), targetID);
          mclient.revertFiles(w.user, w.view, shot, files);
          targetMod.setActionEnabled(false);
        }

        w.mclient.modifyProperties(w.user, w.view, targetMod);
      }

      /*--checking the shot to be modified---*/

      for (String assetToReplace : shotBased.get(shot)) {
        if (assetToReplace.endsWith(lr)) {
          AssetInfo temp = pAssetManager.get(assetToReplace);
          oldRef.add(assetToReplace);
          newRef.add(temp.getNewAsset());
        } else {
          String hiRes = assetToReplace.replace(lr, "");
          AssetInfo temp = pAssetManager.get(hiRes);
          if (temp == null) continue;
          oldRef.add(assetToReplace);
          newRef.add(temp.getNewAsset() + lr);
        } // end else
      } // end for

      if (oldRef.isEmpty() || newRef.isEmpty()) {
        logLine("Shot " + shot + " somehow does not need any changes.");
        continue;
      } // end if

      editShotReferences(shot, targetMod, oldRef, newRef, nameMap);
    } // end for

    /*for(String shot: shotBased.keySet()){
    	//TODO: Check in nodes
    	String msg = "Checked in with UpdateAssetGUI. Removed:\n\t";
    	for(String asset: oldRef)
    		msg+= (asset + " ");

    	msg+="\nAdded:\n\t";
    	for(String asset: newRef)
    		msg+= (asset + " ");

    	mclient.checkIn(w.user, w.view,shot, msg, VersionID.Level.Major);
    }*/

  } // end processShots
  @Override
  public void run(String[] args) {
    try {
      TreeMap<String, LinkedList<String>> parsedArgs = argParser(args);
      if (!checkArgsAndSetParams(parsedArgs)) {
        return;
      }
    } catch (PipelineException ex) {
      System.err.println("There was a problem reading the arguments.\n" + ex.getMessage());
      printHelp();
      return;
    }

    for (String turntableName : turntables) {
      logLine("Doing turntable: " + turntableName);
      for (String passName : passes) {
        logLine("\tDoing pass: "******"\t\tDoing asset: " + as.assetName);
            LairTurntable tt = new LairTurntable(as, turntableName, passName);
            w = new Wrapper(user, view, toolset, client);

            logLine("\t\tFreezing all the textures");
            getLatest(w, as.texGroup, over, froz);

            logLine("\t\tChecking out the final model scene");
            getNewest(w, as.finalScene, keep, pFroz);
            getNewest(w, as.lr_finalScene, keep, pFroz);

            logLine("\t\tChecking out the shader scene.");
            getNewest(w, as.shdScene, keep, pFroz);

            logLine("\t\tChecking out the turntable scene.");
            getNewest(w, tt.turntableScene, keep, pFroz);

            logLine("\t\tChecking out the overRide scene.");
            getNewest(w, tt.ttCamOverMI, keep, pFroz);

            logLine("\t\tChecking out the options scene.");
            getNewest(w, tt.ttOptionsMI, keep, pFroz);

            logLine("\t\tChecking out the camera MI node.");
            getNewest(w, tt.ttCamMI, keep, pFroz);

            logLine("\t\tChecking out the light MI node.");
            getNewest(w, tt.ttLightMI, keep, pFroz);

            logLine("\t\tChecking out the shade MI node.");
            getNewest(w, tt.ttShadeMI, keep, pFroz);

            logLine("\t\tChecking out the geo MI node.");
            getNewest(w, tt.ttGeoMI, keep, pFroz);

            logLine("\t\tChecking out the images node.");
            getNewest(w, tt.ttImages, keep, pFroz);

            logLine("\t\tFixing the turntable node");
            {
              NodeMod mod = client.getWorkingVersion(user, view, tt.turntableScene);
              if (toolset != null) mod.setToolset(toolset);
              client.modifyProperties(user, view, mod);
            }

            logLine("\t\tFixing the camera override node");
            {
              NodeMod mod = client.getWorkingVersion(user, view, tt.ttCamOverMI);
              if (toolset != null) mod.setToolset(toolset);
              BaseAction act = mod.getAction();
              act.setSingleParamValue("ImageWidth", 1280);
              act.setSingleParamValue("ImageHeight", 720);
              act.setSingleParamValue("AspectRatio", 1.777);
              act.setSingleParamValue("Aperture", 1.41732);
              act.setSingleParamValue("OverrideFocal", false);
              act.setSingleParamValue("OverrideClipping", false);
              mod.setAction(act);
              client.modifyProperties(user, view, mod);
            }

            logLine("\t\tFixing the camera node");
            {
              NodeMod mod = client.getWorkingVersion(user, view, tt.ttCamMI);
              if (toolset != null) mod.setToolset(toolset);
              client.modifyProperties(user, view, mod);
            }

            logLine("\t\tFixing the light node");
            {
              NodeMod mod = client.getWorkingVersion(user, view, tt.ttLightMI);
              if (toolset != null) mod.setToolset(toolset);
              client.modifyProperties(user, view, mod);
            }

            logLine("\t\tFixing the geo node");
            {
              NodeMod mod = client.getWorkingVersion(user, view, tt.ttGeoMI);
              if (toolset != null) mod.setToolset(toolset);
              BaseAction act = mod.getAction();
              act.setSingleParamValue("CustomText", true);
              mod.setAction(act);
              client.modifyProperties(user, view, mod);
            }

            logLine("\t\tFixing the shader node");
            {
              NodeMod mod = client.getWorkingVersion(user, view, tt.ttShadeMI);
              if (toolset != null) mod.setToolset(toolset);
              BaseAction act = mod.getAction();
              BaseAction act2 = LairConstants.actionMayaMiShader();
              act2.setSingleParamValues(act);
              mod.setAction(act2);
              JobReqs req = mod.getJobRequirements();
              req.addSelectionKey("MentalRay");
              mod.setJobRequirements(req);
              mod.setExecutionMethod(ExecutionMethod.Parallel);
              mod.setBatchSize(100);
              client.modifyProperties(user, view, mod);
            }

            logLine("\t\tFixing the images node");
            {
              NodeMod mod = client.getWorkingVersion(user, view, tt.ttImages);
              if (toolset != null) mod.setToolset(toolset);
              BaseAction act = mod.getAction();
              act.setSingleParamValue("TexturePath", "$WORKING");
              mod.setAction(act);
              JobReqs req = mod.getJobRequirements();
              req.addSelectionKey("MentalRay");
              mod.setJobRequirements(req);
              mod.setExecutionMethod(ExecutionMethod.Parallel);
              mod.setBatchSize(5);
              client.modifyProperties(user, view, mod);
            }

            logLine(
                "All Done.  Remember to set your export set on the mod node "
                    + "if you want to export a custom part of the body");
          } catch (PipelineException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
      }
    }
  }