/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.dao',
  name: 'F3FileJournal',
  extends: 'foam.dao.AbstractF3FileJournal',
  flags: ['java'],

  implements: [
    'foam.dao.Journal'
  ],

  javaImports: [
    'foam.core.FObject',
    'foam.lib.json.JSONParser',
    'foam.nanos.pm.PM',
    'foam.util.SafetyUtil',
    'java.io.BufferedReader'
  ],

  properties: [
    {
      class: 'foam.dao.DAOProperty',
      name: 'dao'
    }
  ],

  methods: [
    {
      name: 'replay',
      documentation: 'Replays the journal file',
      args: [
        { name: 'x',   type: 'Context' },
        { name: 'dao', type: 'foam.dao.DAO' }
      ],
      javaCode: `
        // count number of entries successfully read
        int successReading = 0;
        JSONParser parser = getParser();

        // NOTE: explicitly calling PM constructor as create only creates
        // a percentage of PMs, but we want all replay statistics
        PM pm = new PM(((foam.dao.AbstractDAO)dao).getOf(), "replay."+getFilename());

        try ( BufferedReader reader = getReader() ) {
          if ( reader == null ) {
            return;
          }
          for ( CharSequence entry ; ( entry = getEntry(reader) ) != null ; ) {
            int length = entry.length();
            if ( length == 0 ) continue;
            if ( COMMENT.matcher(entry).matches() ) continue;

            try {
              char operation = entry.charAt(0);
              String strEntry = entry.subSequence(2, length - 1).toString();

              FObject obj = parser.parseString(strEntry, dao.getOf().getObjClass());
              if ( obj == null ) {
                getLogger().error("Parse error", getParsingErrorMessage(strEntry), "entry:", strEntry);
                continue;
              }

              switch ( operation ) {
                case 'p':
                  foam.core.FObject old = dao.find(obj.getProperty("id"));
                  dao.put(old != null ? mergeFObject(old.fclone(), obj) : obj);
                  break;

                case 'r':
                  dao.remove(obj);
                  break;
              }

              successReading++;
            } catch ( Throwable t ) {
              getLogger().error("Error replaying journal entry:", entry, t);
            }
          }
        } catch ( Throwable t) {
          getLogger().error("Failed to read from journal", t);
        } finally {
          pm.log(x);
          getLogger().log("Successfully read " + successReading + " entries from file: " + getFilename() +" in: "+pm.getTime()+"(ms)");
        }
      `
    }
  ]
});

@@ -814,40 +814,8 @@
 ead%0A
-        int successReading = 0;%0A
     
@@ -1214,16 +1214,17 @@
    for (
+ 
  CharSeq
@@ -1424,17 +1424,16 @@
 ntinue;%0A
-%0A
         
@@ -1440,27 +1440,13 @@
     
-try %7B%0A             
+final
  cha
@@ -1488,17 +1488,21 @@
         
- 
+final
  String 
@@ -1574,17 +1574,157 @@
     
-  FObject
+getLine().enqueue(new foam.util.concurrent.AbstractAssembly() %7B%0A%0A              FObject obj;%0A%0A              public void executeJob() %7B%0A               
  obj
@@ -1779,24 +1779,80 @@
 bjClass());%0A
+              %7D%0A%0A              public void endJob() %7B%0A  
             
@@ -1866,32 +1866,34 @@
 obj == null ) %7B%0A
+  
                 
@@ -1996,26 +1996,28 @@
         
-continue;%0A
+  return;%0A  
         
@@ -2016,33 +2016,34 @@
               %7D%0A
-%0A
+  
               sw
@@ -2075,24 +2075,26 @@
             
+  
 case 'p':%0A  
@@ -2091,16 +2091,18 @@
 se 'p':%0A
+  
         
@@ -2182,24 +2182,26 @@
             
+ 
+ 
 dao.put(old 
@@ -2264,24 +2264,26 @@
             
+  
 break;%0A%0A    
@@ -2290,24 +2290,26 @@
             
+ 
+ 
 case 'r':%0A  
@@ -2306,16 +2306,18 @@
 se 'r':%0A
+  
         
@@ -2357,24 +2357,26 @@
             
+  
 break;%0A     
@@ -2376,35 +2376,38 @@
 ;%0A              
-%7D%0A%0A
+  %7D%0A  
               su
@@ -2438,124 +2438,27 @@
     
-%7D catch ( Throwable t ) %7B%0A              getLogger().error(%22Error replaying journal entry:%22, entry, t);%0A            %7D
+  %7D%0A            %7D);
 %0A   
@@ -2713,16 +2713,19 @@
 () +
+ 
 %22 in: %22
-+
+ + 
 pm.g
@@ -2732,17 +2732,19 @@
 etTime()
-+
+ + 
 %22(ms)%22);
@@ -2768,16 +2768,207 @@
 %60%0A    %7D%0A
+  %5D,%0A  axioms: %5B%0A    %7B%0A      name: 'javaExtras',%0A      buildJavaClass: function(cls) %7B%0A        cls.extras.push(%60%0A          private int successReading = 0;%0A        %60%0A         );%0A      %7D%0A    %7D%0A
   %5D%0A%7D);%0A

use AssemblyLine in Journal replay