imtired method

Future<void> imtired(
  1. Map<String, String> map
)

Implementation

Future<void> imtired(Map<String, String> map) async {
  if (_sheet == null) await _connect();
  await _initHeaders();
  // masterLanguage = config.locales.first;
  // var remoteMasterLangId = remoteHeader.indexOf(masterLanguage) + 1;

  /// get remote keys
  trace('🔑 getting remote Keys ...');
  var remoteKeys = await _table.values.column(1, fromRow: 1);
  trace('found ${remoteKeys.length} remote Keys 🔑');

  var hasKeys = (remoteKeys.length > 1 && remoteKeys[1].isNotEmpty);
  // var startRow = hasKeys ? remoteKeys.length + 1 : 2;

  // trace(remoteKeys);
  if (!hasKeys) {
    trace('⛔ no remote Keys found, generating...');

    /// no checking needed.
    final keys = map.keys.toList();
    final values = map.values.toList();

    /// direct insert!
    await _table.values.insertColumn(
      1,
      keys,
      fromRow: 2,
    );

    await _table.values.insertColumn(
      masterLanguageCol,
      values,
      fromRow: 2,
    );
  }

  /// how much to fill now ?
  var lastRow = await _getLastRemoteRow();
  // trace('Last remote keys row: ', lastRow);

  /// check each lang separately now.
  trace('Validating header columns...');
  var rowsData = await _table.values.allRows(
    fromColumn: 1,
    count: 2,
    fill: true,
  );

  /// inspect 2nd row with access to header :)
  for (var i = 0; i < rowsData[1].length; ++i) {
    var colData = rowsData[1][i];
    var headerValue = rowsData[0][i];
    if (colData.isEmpty &&
        headerValue.isNotEmpty &&
        localHeader.contains(headerValue)) {
      if (headerValue == masterLanguage) {
        trace('Master language ($headerValue) is corrupt, regenerating.');
        await _table.clearColumn(masterLanguageCol, fromRow: 2);
        await _table.values.insertColumn(
          masterLanguageCol,
          map.values.toList(),
          fromRow: 2,
        );
      } else {
        trace(
            'Auto translate column ${i + 1} ($headerValue) x $lastRow rows');
        var data = _generateGoogleTranslateColumn(
          fromRow: 2,
          fromLocaleCol: masterLanguageCol,
          fromLocale: masterLanguage,
          toLocale: headerValue,
          len: lastRow - 1,
        );
        await _table.values.insertColumn(i + 1, data, fromRow: 2);
      }
    }
  }

  /// --- now let's see what changed.
  /// load remote key + master
  print('${yellow('❯')} checking changes with the remote keys...');
  var remoteMap = await _getRemoteMap(masterLanguageCol);
  print('${yellow('❯')} remote keys received ${green('✓')}');

  /// check master language text changes
  trace('Checking remote master String changes...');
  final rowsToUpdate = <int, List<String>>{};

  List<String> buildGTRow({
    required int row,
    required String keyText,
    required String masterText,
  }) {
    var master = config.locales.first;
    var out = <String>[];
    for (var i = 0; i < remoteHeader.length; ++i) {
      var header = remoteHeader[i];
      if (header == 'keys') {
        out.add(keyText);
      } else if (localHeader.contains(header)) {
        if (header == master) {
          out.add(masterText);
        } else {
          var data = _getTranslateCell(row, header);
          out.add(data);
          // out.add(_getCellGTranslate(row, master, header));
        }
      } else {
        out.add('');
      }
    }
    return out;
  }

  for (var k in map.keys) {
    if (!remoteMap.containsKey(k)) continue;
    var localText = map[k]!;
    var remoteText = remoteMap[k]!;
    if (remoteText != localText) {
      var row = remoteKeys.indexOf(k) + 1;
      rowsToUpdate[row] = buildGTRow(
        row: row,
        masterText: localText,
        keyText: k,
      );
      trace('- row $row: \n\t', remoteText, '\n\t != \n\t', localText);
    }
  }
  if (rowsToUpdate.isNotEmpty) {
    trace('Updating ${rowsToUpdate.length} rows...');
    trace(rowsToUpdate);
    await _table.batchUpdateRows(rowsToUpdate);
    trace('Done updating rows with mismatch text.');
  }

  /// REMOVE KEYS

  var deletedKeys = [];
  for (var k in remoteMap.keys) {
    if (!map.containsKey(k) && k.isNotEmpty) {
      deletedKeys.add(k);
    }
  }

  if (deletedKeys.isNotEmpty) {
    trace(
      'keys nonexistent in the local map: \n-',
      deletedKeys.join('  \n- '),
    );

    /// we will delete the rows remotely?
    // var autoDelete = deletedKeys.length < 2;
    var autoDelete = true;
    if (autoDelete) {
      //// clear the fields!
      // _table.batchClearRows(rows)
      var clearRows = <int>[];
      for (var k in deletedKeys) {
        var row = remoteKeys.indexOf(k) + 1;
        clearRows.add(row);
        // await _table.deleteRow(row);
        // remoteMap.remove(k);
        // remoteKeys.remove(k);
        // trace('Row $row deleted.');
      }

      if (clearRows.isNotEmpty) {
        trace(
            '${clearRows.length} rows will be cleared ( ${clearRows.join((', '))} )');
        var result = await _table.batchClearRows(clearRows);
        trace('Clear rows result:', result);
        if (result) {
          for (var row in clearRows) {
            var k = remoteKeys[row - 1];
            remoteMap.remove(k);
            remoteKeys[row - 1] = '';
            // remoteKeys.remove(k);
          }
          clearRows.clear();
          trace('Rows clearing successful');
        }
      }
    } else {
      /// check if its a batch!
      trace('You will have to manually delete:');
      for (var k in deletedKeys) {
        // _table.clearRow(row, fromColumn: 1, length: 12, count: 20);
        var row = remoteKeys.indexOf(k) + 1;
        trace('- row $row');
      }
    }
  }

  /// ADD NEW KEYS
  var addedKeys = [];
  for (var k in map.keys) {
    if (!remoteMap.containsKey(k)) {
      addedKeys.add(k);
    }
  }
  if (addedKeys.isNotEmpty) {
    trace(
      'new keys inserted:\n - ',
      addedKeys.join('\n - '),
    );

    /// we will add the rows to their positions?
    // var addToEnd = addedKeys.length > 4;
    var addToEnd = true;
    final keys0 = map.keys.toList(growable: false);
    if (addToEnd) {
      var lastRow = await _getLastRemoteRow() + 1;
      trace('We will add new records at the end.');

      /// ( row > $lastRow )
      var insertRows = <List<String>>[];
      var row = lastRow;
      for (var k in addedKeys) {
        // ++lastRow;
        // await _table.insertRow(row);
        var rowData = _getNewRowKey(
          row: row,
          key: k,
          text: map[k]!,
          remoteHeader: remoteHeader,
          localHeader: localHeader,
        );
        insertRows.add(rowData);
        ++row;
        // trace('row $row built');
      }
      trace('Inserting ${insertRows.length} record(s)');
      // await _table.values.insertRows(lastRow, insertRows);
      try {
        await _table.values.appendRows(insertRows);
      } catch (e) {
        error('ERROR: $e');
        if (e is GSheetsException) {
          if (e.cause.toLowerCase().contains('not have permission')) {
            error(badCredentialsHelp);
          }
        }
        exit(3);
      }
      trace('🙂 Append rows complete');
    } else {
      for (var k in addedKeys) {
        var row = keys0.indexOf(k) + 2;
        await _table.insertRow(row);
        var rowData = _getNewRowKey(
          row: row,
          key: k,
          text: map[k]!,
          remoteHeader: remoteHeader,
          localHeader: localHeader,
        );
        await _table.values.insertRow(row, rowData);
        trace('row $row built');
      }
    }
  }

  if (remoteKeys.contains('')) {
    var numBlankSpaces = remoteKeys.where((text) => text.isEmpty).length;
    trace('total blank key rows: ', red('$numBlankSpaces'));

    /// TODO: Clean up EMPTY keys.
    if (numBlankSpaces > 1) {
      trace('Empty keys detected: $numBlankSpaces');
      var result = await _removeTableWhitespaces();
      var count = result['replies']?.first['deleteDuplicates']
              ?['duplicatesRemovedCount'] ??
          0;
      trace('Duplicated rows deleted: $count');
    }

    /// detect the first row!🎯
    var firstCleanIndex = remoteKeys.indexOf('');
    if (firstCleanIndex > 1) {
      var row = firstCleanIndex + 1;
      await _table.deleteRow(row);
      print('Empty row ${red('$row')} deleted.');
    }
  }

  // trace('Current row count: ', _table.rowCount);

  // trace(remoteKeys.length, ':', remoteValues.length);
  // trace(remoteMap);
}