text: import os
  import json
  
  from avalon import api, harmony
  import openpype.lib
  
  
  copy_files = """function copyFile(srcFilename, dstFilename)
  {
      var srcFile = new PermanentFile(srcFilename);
      var dstFile = new PermanentFile(dstFilename);
      srcFile.copy(dstFile);
  }
  """
  
  import_files = """var PNGTransparencyMode = 1; //Premultiplied with Black
  var TGATransparencyMode = 0; //Premultiplied with Black
  var SGITransparencyMode = 0; //Premultiplied with Black
  var LayeredPSDTransparencyMode = 1; //Straight
  var FlatPSDTransparencyMode = 2; //Premultiplied with White
  
  function getUniqueColumnName( column_prefix )
  {
      var suffix = 0;
      // finds if unique name for a column
      var column_name = column_prefix;
      while(suffix < 2000)
      {
          if(!column.type(column_name))
          break;
  
          suffix = suffix + 1;
          column_name = column_prefix + "_" + suffix;
      }
      return column_name;
  }
  
  function import_files(args)
  {
      var root = args[0];
      var files = args[1];
      var name = args[2];
      var start_frame = args[3];
  
      var vectorFormat = null;
      var extension = null;
      var filename = files[0];
  
      var pos = filename.lastIndexOf(".");
      if( pos < 0 )
          return null;
  
      extension = filename.substr(pos+1).toLowerCase();
  
      if(extension == "jpeg")
          extension = "jpg";
      if(extension == "tvg")
      {
          vectorFormat = "TVG"
          extension ="SCAN"; // element.add() will use this.
      }
  
      var elemId = element.add(
          name,
          "BW",
          scene.numberOfUnitsZ(),
          extension.toUpperCase(),
          vectorFormat
      );
      if (elemId == -1)
      {
          // hum, unknown file type most likely -- let's skip it.
          return null; // no read to add.
      }
  
      var uniqueColumnName = getUniqueColumnName(name);
      column.add(uniqueColumnName , "DRAWING");
      column.setElementIdOfDrawing(uniqueColumnName, elemId);
  
      var read = node.add(root, name, "READ", 0, 0, 0);
      var transparencyAttr = node.getAttr(
          read, frame.current(), "READ_TRANSPARENCY"
      );
      var opacityAttr = node.getAttr(read, frame.current(), "OPACITY");
      transparencyAttr.setValue(true);
      opacityAttr.setValue(true);
  
      var alignmentAttr = node.getAttr(read, frame.current(), "ALIGNMENT_RULE");
      alignmentAttr.setValue("ASIS");
  
      var transparencyModeAttr = node.getAttr(
          read, frame.current(), "applyMatteToColor"
      );
      if (extension == "png")
          transparencyModeAttr.setValue(PNGTransparencyMode);
      if (extension == "tga")
          transparencyModeAttr.setValue(TGATransparencyMode);
      if (extension == "sgi")
          transparencyModeAttr.setValue(SGITransparencyMode);
      if (extension == "psd")
          transparencyModeAttr.setValue(FlatPSDTransparencyMode);
      if (extension == "jpg")
          transparencyModeAttr.setValue(LayeredPSDTransparencyMode);
  
      node.linkAttr(read, "DRAWING.ELEMENT", uniqueColumnName);
  
      if (files.length == 1)
      {
          // Create a drawing drawing, 'true' indicate that the file exists.
          Drawing.create(elemId, 1, true);
          // Get the actual path, in tmp folder.
          var drawingFilePath = Drawing.filename(elemId, "1");
          copyFile(files[0], drawingFilePath);
          // Expose the image for the entire frame range.
          for( var i =0; i <= frame.numberOf() - 1; ++i)
          {
              timing = start_frame + i
              column.setEntry(uniqueColumnName, 1, timing, "1");
          }
      } else {
          // Create a drawing for each file.
          for( var i =0; i <= files.length - 1; ++i)
          {
              timing = start_frame + i
              // Create a drawing drawing, 'true' indicate that the file exists.
              Drawing.create(elemId, timing, true);
              // Get the actual path, in tmp folder.
              var drawingFilePath = Drawing.filename(elemId, timing.toString());
              copyFile( files[i], drawingFilePath );
  
              column.setEntry(uniqueColumnName, 1, timing, timing.toString());
          }
      }
  
      var green_color = new ColorRGBA(0, 255, 0, 255);
      node.setColor(read, green_color);
  
      return read;
  }
  import_files
  """
  
  replace_files = """var PNGTransparencyMode = 1; //Premultiplied with Black
  var TGATransparencyMode = 0; //Premultiplied with Black
  var SGITransparencyMode = 0; //Premultiplied with Black
  var LayeredPSDTransparencyMode = 1; //Straight
  var FlatPSDTransparencyMode = 2; //Premultiplied with White
  
  function replace_files(args)
  {
      var files = args[0];
      MessageLog.trace(files);
      MessageLog.trace(files.length);
      var _node = args[1];
      var start_frame = args[2];
  
      var _column = node.linkedColumn(_node, "DRAWING.ELEMENT");
      var elemId = column.getElementIdOfDrawing(_column);
  
      // Delete existing drawings.
      var timings = column.getDrawingTimings(_column);
      for( var i =0; i <= timings.length - 1; ++i)
      {
          column.deleteDrawingAt(_column, parseInt(timings[i]));
      }
  
  
      var filename = files[0];
      var pos = filename.lastIndexOf(".");
      if( pos < 0 )
          return null;
      var extension = filename.substr(pos+1).toLowerCase();
  
      if(extension == "jpeg")
          extension = "jpg";
  
      var transparencyModeAttr = node.getAttr(
          _node, frame.current(), "applyMatteToColor"
      );
      if (extension == "png")
          transparencyModeAttr.setValue(PNGTransparencyMode);
      if (extension == "tga")
          transparencyModeAttr.setValue(TGATransparencyMode);
      if (extension == "sgi")
          transparencyModeAttr.setValue(SGITransparencyMode);
      if (extension == "psd")
          transparencyModeAttr.setValue(FlatPSDTransparencyMode);
      if (extension == "jpg")
          transparencyModeAttr.setValue(LayeredPSDTransparencyMode);
  
      if (files.length == 1)
      {
          // Create a drawing drawing, 'true' indicate that the file exists.
          Drawing.create(elemId, 1, true);
          // Get the actual path, in tmp folder.
          var drawingFilePath = Drawing.filename(elemId, "1");
          copyFile(files[0], drawingFilePath);
          MessageLog.trace(files[0]);
          MessageLog.trace(drawingFilePath);
          // Expose the image for the entire frame range.
          for( var i =0; i <= frame.numberOf() - 1; ++i)
          {
              timing = start_frame + i
              column.setEntry(_column, 1, timing, "1");
          }
      } else {
          // Create a drawing for each file.
          for( var i =0; i <= files.length - 1; ++i)
          {
              timing = start_frame + i
              // Create a drawing drawing, 'true' indicate that the file exists.
              Drawing.create(elemId, timing, true);
              // Get the actual path, in tmp folder.
              var drawingFilePath = Drawing.filename(elemId, timing.toString());
              copyFile( files[i], drawingFilePath );
  
              column.setEntry(_column, 1, timing, timing.toString());
          }
      }
  
      var green_color = new ColorRGBA(0, 255, 0, 255);
      node.setColor(_node, green_color);
  }
  replace_files
  """
  
  
  class BackgroundLoader(api.Loader):
      """Load images
      Stores the imported asset in a container named after the asset.
      """
      families = ["background"]
      representations = ["json"]
  
      def load(self, context, name=None, namespace=None, data=None):
  
          with open(self.fname) as json_file:
              data = json.load(json_file)
  
          layers = list()
  
          for child in data['children']:
              if child.get("filename"):
                  layers.append(child["filename"])
              else:
                  for layer in child['children']:
                      if layer.get("filename"):
                          layers.append(layer["filename"])
  
          bg_folder = os.path.dirname(self.fname)
  
          subset_name = context["subset"]["name"]
          # read_node_name += "_{}".format(uuid.uuid4())
          container_nodes = []
  
          for layer in sorted(layers):
              file_to_import = [
                  os.path.join(bg_folder, layer).replace("\\", "/")
              ]
  
              read_node = harmony.send(
                  {
                      "function": copy_files + import_files,
                      "args": ["Top", file_to_import, layer, 1]
                  }
              )["result"]
              container_nodes.append(read_node)
  
          return harmony.containerise(
              subset_name,
              namespace,
              subset_name,
              context,
              self.__class__.__name__,
              nodes=container_nodes
          )
  
      def update(self, container, representation):
  
          path = api.get_representation_path(representation)
  
          with open(path) as json_file:
              data = json.load(json_file)
  
          layers = list()
  
          for child in data['children']:
              if child.get("filename"):
                  print(child["filename"])
                  layers.append(child["filename"])
              else:
                  for layer in child['children']:
                      if layer.get("filename"):
                          print(layer["filename"])
                          layers.append(layer["filename"])
  
          bg_folder = os.path.dirname(path)
  
          path = api.get_representation_path(representation)
  
          print(container)
  
          for layer in sorted(layers):
              file_to_import = [
                  os.path.join(bg_folder, layer).replace("\\", "/")
              ]
              print(20 * "#")
              print(f"FILE TO REPLACE: {file_to_import}")
              print(f"LAYER: {layer}")
              node = harmony.find_node_by_name(layer, "READ")
              print(f"{node}")
  
              if node in container['nodes']:
                  harmony.send(
                      {
                          "function": copy_files + replace_files,
                          "args": [file_to_import, node, 1]
                      }
                  )
              else:
                  read_node = harmony.send(
                      {
                          "function": copy_files + import_files,
                          "args": ["Top", file_to_import, layer, 1]
                      }
                  )["result"]
                  container['nodes'].append(read_node)
  
              # Colour node.
              sig = harmony.signature("set_color")
              func = """function %s(args){
                  for( var i =0; i <= args[0].length - 1; ++i)
                  {
                      var red_color = new ColorRGBA(255, 0, 0, 255);
                      var green_color = new ColorRGBA(0, 255, 0, 255);
                      if (args[1] == "red"){
                          node.setColor(args[0], red_color);
                      }
                      if (args[1] == "green"){
                          node.setColor(args[0], green_color);
                      }
                  }
              }
              %s
              """ % (sig, sig)
              if openpype.lib.is_latest(representation):
                  harmony.send({"function": func, "args": [node, "green"]})
              else:
                  harmony.send({"function": func, "args": [node, "red"]})
  
          harmony.imprint(
              container['name'], {"representation": str(representation["_id"]),
                                  "nodes": container['nodes']}
          )
  
      def remove(self, container):
          for node in container.get("nodes"):
  
              func = """function deleteNode(_node)
              {
                  node.deleteNode(_node, true, true);
              }
              deleteNode
              """
              harmony.send(
                  {"function": func, "args": [node]}
              )
              harmony.imprint(container['name'], {}, remove=True)
  
      def switch(self, container, representation):
          self.update(container, representation)
  