#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""Test the timeline view."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

from absl import app
import mock

from grr_response_core.lib.rdfvalues import client_fs as rdf_client_fs
from grr_response_core.lib.rdfvalues import paths as rdf_paths

from grr_response_server.flows.general import filesystem
from grr_response_server.gui import api_call_router_with_approval_checks
from grr_response_server.gui import gui_test_lib
from grr_response_server.gui.api_plugins import vfs as api_vfs
from grr.test_lib import fixture_test_lib
from grr.test_lib import test_lib


class TestTimeline(gui_test_lib.GRRSeleniumTest):
  """Test the timeline view interface."""

  TIMELINE_ITEMS_PER_FILE = 3

  def setUp(self):
    super(TestTimeline, self).setUp()
    # Prepare our fixture.
    self.client_id = "C.0000000000000001"
    fixture_test_lib.ClientFixture(self.client_id)
    self.CreateFileWithTimeline(self.client_id, "c/proc/changed.txt",
                                rdf_paths.PathSpec.PathType.OS, self.token)
    self.CreateFileWithTimeline(self.client_id, "c/proc/other.txt",
                                rdf_paths.PathSpec.PathType.OS, self.token)
    self.RequestAndGrantClientApproval(self.client_id)

  @staticmethod
  def CreateFileWithTimeline(client_id, path, path_type, token):
    """Add a file with timeline."""

    # Add a version of the file at gui_test_lib.TIME_0. Since we write all MAC
    # times, this will result in three timeline items.
    stat_entry = rdf_client_fs.StatEntry()
    stat_entry.pathspec.path = path
    stat_entry.pathspec.pathtype = path_type
    stat_entry.st_atime = gui_test_lib.TIME_0.AsSecondsSinceEpoch() + 1000
    stat_entry.st_mtime = gui_test_lib.TIME_0.AsSecondsSinceEpoch()
    stat_entry.st_ctime = gui_test_lib.TIME_0.AsSecondsSinceEpoch() - 1000

    with test_lib.FakeTime(gui_test_lib.TIME_0):
      filesystem.WriteStatEntries([stat_entry], client_id)

    # Add a version with a stat entry, but without timestamps.
    stat_entry = rdf_client_fs.StatEntry()
    stat_entry.pathspec.path = path
    stat_entry.pathspec.pathtype = path_type
    stat_entry.st_ino = 99

    with test_lib.FakeTime(gui_test_lib.TIME_1):
      filesystem.WriteStatEntries([stat_entry], client_id)

  def testTimelineContainsAllChangesForDirectory(self):
    # Open VFS view for client 1 on a specific location.
    self.Open("/#c=C.0000000000000001&main=VirtualFileSystemView"
              "&t=_fs-os-c-proc")

    # We have to wait until the "proc" node gets highlighted in the tree,
    # as the tree expansion may take time and happen in multiple steps.
    # On every expansion step, the view mode will be switched to "file list",
    # even if "timeline" mode was previously active.
    self.WaitUntil(self.IsElementPresent,
                   "css=a.jstree-clicked:contains('proc')")