#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Tests for the status view."""

from __future__ import unicode_literals

import unittest
try:
  import mock  # pylint: disable=import-error
except ImportError:
  from unittest import mock
import sys

from dfvfs.lib import definitions as dfvfs_definitions

import plaso

from plaso.cli import status_view
from plaso.engine import processing_status

from tests.cli import test_lib


class StatusViewTest(test_lib.CLIToolTestCase):
  """Tests for the status view."""

  # pylint: disable=protected-access

  def _MockTime(self):
    """Mock function to simulate time.time()

    Returns:
      int: stored time via self._mocked_time"""
    return self._mocked_time

  def setUp(self):
    """Makes preparations before running an individual test."""

    self.mock_time = mock.patch(
        'plaso.cli.status_view.time.time', self._MockTime)
    self._mocked_time = 0
    self.mock_time.start()

  def tearDown(self):
    """Cleans up after running an individual test."""
    self.mock_time.stop()

  def _CheckOutput(self, output, expected_output):
    """Compares the output against the expected output.

    The actual processing time is ignored, since it can vary.

    Args:
      output (str): tool output.
      expected_output (list[str]): expected tool output.
    """
    output = output.split('\n')

    self.assertEqual(output[:4], expected_output[:4])
    self.assertTrue(output[4].startswith('Processing time\t\t: '))
    self.assertEqual(output[5:], expected_output[5:])

  # TODO: add tests for _ClearScreen
  # TODO: add tests for _FormatAnalysisStatusTableRow
  # TODO: add tests for _FormatExtractionStatusTableRow
  # TODO: add tests for _FormatSizeInUnitsOf1024
  # TODO: add tests for _PrintAnalysisStatusHeader
  # TODO: add tests for _PrintAnalysisStatusUpdateLinear
  # TODO: add tests for _PrintAnalysisStatusUpdateWindow
  # TODO: add tests for _PrintEventsStatus

  def testPrintExtractionStatusUpdateLinear(self):
    """Tests the PrintExtractionStatusUpdateLinear function."""
    output_writer = test_lib.TestOutputWriter()

    test_view = status_view.StatusView(output_writer, 'test_tool')
    test_view.SetSourceInformation(
        '/test/source/path', dfvfs_definitions.SOURCE_TYPE_DIRECTORY)

    process_status = processing_status.ProcessingStatus()
    process_status.UpdateForemanStatus(
        'f_identifier', 'f_status', 123, 0,
        'f_test_file', 1, 29, 3, 456, 5, 6, 9, 10, 7, 8)
    test_view._PrintExtractionStatusUpdateLinear(process_status)

    expected_output = (
        'Processing time: 00:00:00\n'
        'f_identifier (PID: 123) status: f_status, events produced: 456, '
        'file: f_test_file\n'
        '\n')

    output = output_writer.ReadOutput()
    self.assertEqual(output, expected_output)

    process_status.UpdateWorkerStatus(
        'w_identifier', 'w_status', 123, 0,
        'w_test_file', 1, 2, 3, 4, 5, 6, 9, 10, 7, 8)
    test_view._PrintExtractionStatusUpdateLinear(process_status)

    expected_output = (
        'Processing time: 00:00:00\n'
        'f_identifier (PID: 123) status: f_status, events produced: 456, '
        'file: f_test_file\n'
        'w_identifier (PID: 123) status: w_status, events produced: 4, '
        'file: w_test_file\n'
        '\n')

    output = output_writer.ReadOutput()
    self.assertEqual(output, expected_output)

  def testPrintExtractionStatusUpdateWindow(self):
    """Tests the _PrintExtractionStatusUpdateWindow function."""
    output_writer = test_lib.TestOutputWriter()

    test_view = status_view.StatusView(output_writer, 'test_tool')
    test_view.SetSourceInformation(
        '/test/source/path', dfvfs_definitions.SOURCE_TYPE_DIRECTORY)

    process_status = processing_status.ProcessingStatus()
    process_status.UpdateForemanStatus(
        'f_identifier', 'f_status', 123, 0,
        'f_test_file', 1, 29, 3, 456, 5, 6, 9, 10, 7, 8)
    test_view._PrintExtractionStatusUpdateWindow(process_status)

    table_header = (
        'Identifier      '
        'PID     '
        'Status          '
        'Memory          '
        'Sources         '
        'Events          '
        'File')

    if not sys.platform.startswith('win'):