/*
 * 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.DeviceAdminReceiver.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;
        }
        // Order, so that most recent batch token is first.
        Arrays.sort(networkLogsFiles, Collections.reverseOrder());
        return networkLogsFiles[0];
    }

    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;
    }
}

@@ -1189,16 +1189,45 @@
 ctions;%0A
+import java.util.Comparator;%0A
 import j
@@ -4184,22 +4184,15 @@
  // 
-Order, so that
+Get the
  mos
@@ -4209,126 +4209,397 @@
 atch
- token is first.%0A        Arrays.sort(networkLogsFiles, Collections.reverseOrder());%0A        return networkLogsFiles%5B0%5D
+. Batches are sorted by the timestamp they were last modified%0A        // in, also corresponding to the last value in their file names.%0A        return Collections.max(%0A            // Can't use Comparator.comparing(): requires default interface methods (min_sdk %3E= 24).%0A            Arrays.asList(networkLogsFiles),%0A            (f1, f2) -%3E Long.signum (f1.lastModified() - f2.lastModified()))
 ;%0A  

Fix network logs retrieval to get the freshest batch of logs.