/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.afwsamples.testdpc.policy;

import static com.afwsamples.testdpc.CommonReceiverOperations.NETWORK_LOGS_FILE_PREFIX;

import android.annotation.TargetApi;
import android.app.ListFragment;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.afwsamples.testdpc.R;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.PatternSyntaxException;

/** Display the last retrieved batch of NetworkEvents. */
@TargetApi(VERSION_CODES.O)
public class NetworkLogsFragment extends ListFragment {

  private static final String TAG = "NetworkLogsFragment";

  private List<String> mLogs = new ArrayList<>();
  private ArrayAdapter<String> mAdapter;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mAdapter =
        new ArrayAdapter<>(
            getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1, mLogs);
    setListAdapter(mAdapter);
  }

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mLogs = fetchEvents();
    showEvents(mLogs);
  }

  private List<String> fetchEvents() {
    File logsFile = findLastBatch();
    if (logsFile == null) {
      return Collections.emptyList();
    }
    BufferedReader reader = null;
    try {
      long batchToken = determineBatchToken(logsFile.getName());
      mAdapter.add(getContext().getString(R.string.on_network_logs_available_success, batchToken));
      reader = new BufferedReader(new FileReader(logsFile));
      ArrayList<String> events = new ArrayList<>();
      String line;
      while ((line = reader.readLine()) != null) {
        Log.v(TAG, "found line: " + line);
        events.add(line);
      }
      return events;
    } catch (NumberFormatException | IOException e) {
      mAdapter.add(getString(R.string.on_network_logs_available_failure));
    } finally {
      try {
        if (reader != null) {
          reader.close();
        }
      } catch (IOException e) {
        // no-op
      }
    }
    return Collections.emptyList();
  }

  private void showEvents(List<String> logs) {
    if (logs == null) {
      Log.w(TAG, "logs == null, are you polling too early?");
      mAdapter.add(getString(R.string.on_network_logs_available_failure));
    } else {
      Log.d(TAG, "Incoming logs size: " + logs.size());
      mAdapter.addAll(mLogs);
      ListView listView = NetworkLogsFragment.this.getListView();
      listView.setSelection(listView.getCount() - 1);
    }
  }

  private File findLastBatch() {
    File path = getContext().getExternalFilesDir(null);
    if (path == null) {
      return null;
    }
    File[] networkLogsFiles =
        path.listFiles((File file, String s) -> s.startsWith(NETWORK_LOGS_FILE_PREFIX));
    if (networkLogsFiles == null || networkLogsFiles.length == 0) {
      return null;
    }
    // Get the most recent batch. Batches are sorted by the timestamp they were last modified
    // in, also corresponding to the last value in their file names.
    return Collections.max(
        // Can't use Comparator.comparing(): requires default interface methods (min_sdk >= 24).
        Arrays.asList(networkLogsFiles),
        (f1, f2) -> Long.signum(f1.lastModified() - f2.lastModified()));
  }

  private long determineBatchToken(String fileName) throws NumberFormatException {
    // Name should be "network_logs_X_Y.txt", where X is the batch token
    String[] fileNameArr = fileName.split("_");
    if (fileNameArr.length <= 2) {
      throw new NumberFormatException("Failed parsing the batch from file: " + fileName);
    }
    long batchToken;
    try {
      batchToken = Long.parseLong(fileNameArr[2]);
    } catch (PatternSyntaxException e) {
      throw new NumberFormatException("Failed parsing the batch from file: " + fileName);
    }
    return batchToken;
  }
}
