# Path: dftimewolf/config.py
# class Config(object):
#   def GetExtra(cls, name: str='') -> Dict[str, Any]:
#   def LoadExtra(cls, filename: str) -> bool:
#   def LoadExtraData(cls, json_string: bytes) -> None:
#   def ClearExtra(cls) -> None:
# 
# Path: dftimewolf/lib/errors.py
# class DFTimewolfError(Exception):
# class BadConfigurationError(DFTimewolfError):
# class RecipeParseError(DFTimewolfError):
# class CommandLineParseError(DFTimewolfError):
# class CriticalError(DFTimewolfError):
#   def __init__(self,
#                message: Optional[str]=None,
#                name: Optional[str]=None,
#                stacktrace: Optional[str]=None,
#                critical: bool=False,
#                unexpected: bool=False) -> None:
# 
# Path: dftimewolf/lib/state.py
# T = TypeVar("T", bound="interface.AttributeContainer")  # pylint: disable=invalid-name,line-too-long
# NEW_ISSUE_URL = 'https://github.com/log2timeline/dftimewolf/issues/new'
# class DFTimewolfState(object):
#   def __init__(self, config: Type[Config]) -> None:
#   def _InvokeModulesInThreads(self, callback: Callable[[Any], Any]) -> None:
#   def ImportRecipeModules(self, module_locations: Dict[str, str]) -> None:
#   def LoadRecipe(self,
#                  recipe: Dict[str, Any],
#                  module_locations: Dict[str, str]) -> None:
#   def FormatExecutionPlan(self) -> str:
#   def LogExecutionPlan(self) -> None:
#   def AddToCache(self, name: str, value: Any) -> None:
#   def GetFromCache(self, name: str, default_value: Any=None) -> Any:
#   def StoreContainer(self, container: "interface.AttributeContainer") -> None:
#   def GetContainers(self,
#                     container_class: Type[T],
#                     pop: bool=False) -> Sequence[T]:
#   def DedupeContainers(self, container_class: Type[T]) -> None:
#   def _SetupModuleThread(self, module_definition: Dict[str, str]) -> None:
#   def SetupModules(self) -> None:
#   def _RunModuleThread(self, module_definition: Dict[str, str]) -> None:
#   def RunPreflights(self) -> None:
#   def CleanUpPreflights(self) -> None:
#   def InstantiateModule(self, module_name: str) -> "dftw_module.BaseModule":
#   def RunModules(self) -> None:
#   def RegisterStreamingCallback(
#       self,
#       target: Callable[["interface.AttributeContainer"], Any],
#       container_type: Type["interface.AttributeContainer"]) -> None:
#   def StreamContainer(self, container: "interface.AttributeContainer") -> None:
#   def AddError(self, error: DFTimewolfError) -> None:
#   def CleanUp(self) -> None:
#   def CheckErrors(self, is_global: bool=False) -> None:
# 
# Path: dftimewolf/lib/collectors/gsheets.py
# class GoogleSheetsCollector(module.BaseModule):
#   SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']
#   _CREDENTIALS_FILENAME = '.dftimewolf_google_sheets_credentials.json'
#   _CLIENT_SECRET_FILENAME = '.dftimewolf_google_sheets_client_secret.json'
#   def __init__(self,
#                state: DFTimewolfState,
#                name: Optional[str] = None,
#                critical: bool = False) -> None:
#   def SetUp(self,
#             spreadsheet: str,
#             sheet_names: List[str],
#             validate_columns: bool) -> None:
#   def Process(self) -> None:
#   def _GetCredentials(self) -> Credentials:
#   def _ValidateSpreadSheetId(self, spreadsheet: str) -> str:
#   def _ExtractEntriesFromSheet(self,
#                                spreadsheet_id: str,
#                                sheet_title: str) -> pd.DataFrame:


import unittest
import mock
from dftimewolf import config
from dftimewolf.lib import errors
from dftimewolf.lib import state
from dftimewolf.lib.collectors import gsheets


# pylint: disable=line-too-long
VALID_SHEET = {'range': 'Sheet1!A1:Z1000', 'majorDimension': 'ROWS', 'values': [
    ['message', 'timestamp', 'datetime', 'timestamp_desc ', 'extra_field_1 ', 'extra_field_2'],
    ['A message', '1331698658276340', '2015-07-24T19:01:01+00:00', 'Write time', 'foo ', 'bar'],
    ['', '1331698658276340', '2016-07-24T19:01:01+00:00', 'creation time', 'foo', ''],
    ['A message', '', '', 'modified time', 'foo', 'bar']]}
# Missing "datetime" columnd
INVALID_SHEET = {'range': 'Sheet2!A1:Y1000', 'majorDimension': 'ROWS', 'values': [
    ['message', 'timestamp', 'timestamp_desc ', 'extra_field_1 ', 'extra_field_2'],
    ['A message', '1331698658276340', 'Write time', 'foo ', 'bar'],
    ['', '1331698658276340', 'creation time', 'foo', ''],
    ['A message', '', 'modified time', 'foo', 'bar']]}
# pylint: enable=line-too-long


class GoogleSheetsCollectorTest(unittest.TestCase):
  """Tests for the Google Sheets collector module ."""

  def testInitialization(self):
    """Tests that the collector can be initialized."""
    test_state = state.DFTimewolfState(config.Config)
    collector = gsheets.GoogleSheetsCollector(test_state)
    self.assertIsNotNone(collector)

  # pylint: disable=protected-access
  def testValidateSpreadSheetId(self):
    """Tests that the collector validate and extract spreadsheet id."""
    test_state = state.DFTimewolfState(config.Config)

# Path: dftimewolf/config.py
# class Config(object):
#   def GetExtra(cls, name: str='') -> Dict[str, Any]:
#   def LoadExtra(cls, filename: str) -> bool:
#   def LoadExtraData(cls, json_string: bytes) -> None:
#   def ClearExtra(cls) -> None:
# 
# Path: dftimewolf/lib/errors.py
# class DFTimewolfError(Exception):
# class BadConfigurationError(DFTimewolfError):
# class RecipeParseError(DFTimewolfError):
# class CommandLineParseError(DFTimewolfError):
# class CriticalError(DFTimewolfError):
#   def __init__(self,
#                message: Optional[str]=None,
#                name: Optional[str]=None,
#                stacktrace: Optional[str]=None,
#                critical: bool=False,
#                unexpected: bool=False) -> None:
# 
# Path: dftimewolf/lib/state.py
# T = TypeVar("T", bound="interface.AttributeContainer")  # pylint: disable=invalid-name,line-too-long
# NEW_ISSUE_URL = 'https://github.com/log2timeline/dftimewolf/issues/new'
# class DFTimewolfState(object):
#   def __init__(self, config: Type[Config]) -> None:
#   def _InvokeModulesInThreads(self, callback: Callable[[Any], Any]) -> None:
#   def ImportRecipeModules(self, module_locations: Dict[str, str]) -> None:
#   def LoadRecipe(self,
#                  recipe: Dict[str, Any],
#                  module_locations: Dict[str, str]) -> None:
#   def FormatExecutionPlan(self) -> str:
#   def LogExecutionPlan(self) -> None:
#   def AddToCache(self, name: str, value: Any) -> None:
#   def GetFromCache(self, name: str, default_value: Any=None) -> Any:
#   def StoreContainer(self, container: "interface.AttributeContainer") -> None:
#   def GetContainers(self,
#                     container_class: Type[T],
#                     pop: bool=False) -> Sequence[T]:
#   def DedupeContainers(self, container_class: Type[T]) -> None:
#   def _SetupModuleThread(self, module_definition: Dict[str, str]) -> None:
#   def SetupModules(self) -> None:
#   def _RunModuleThread(self, module_definition: Dict[str, str]) -> None:
#   def RunPreflights(self) -> None:
#   def CleanUpPreflights(self) -> None:
#   def InstantiateModule(self, module_name: str) -> "dftw_module.BaseModule":
#   def RunModules(self) -> None:
#   def RegisterStreamingCallback(
#       self,
#       target: Callable[["interface.AttributeContainer"], Any],
#       container_type: Type["interface.AttributeContainer"]) -> None:
#   def StreamContainer(self, container: "interface.AttributeContainer") -> None:
#   def AddError(self, error: DFTimewolfError) -> None:
#   def CleanUp(self) -> None:
#   def CheckErrors(self, is_global: bool=False) -> None:
# 
# Path: dftimewolf/lib/collectors/gsheets.py
# class GoogleSheetsCollector(module.BaseModule):
#   SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']
#   _CREDENTIALS_FILENAME = '.dftimewolf_google_sheets_credentials.json'
#   _CLIENT_SECRET_FILENAME = '.dftimewolf_google_sheets_client_secret.json'
#   def __init__(self,
#                state: DFTimewolfState,
#                name: Optional[str] = None,
#                critical: bool = False) -> None:
#   def SetUp(self,
#             spreadsheet: str,
#             sheet_names: List[str],
#             validate_columns: bool) -> None:
#   def Process(self) -> None:
#   def _GetCredentials(self) -> Credentials:
#   def _ValidateSpreadSheetId(self, spreadsheet: str) -> str:
#   def _ExtractEntriesFromSheet(self,
#                                spreadsheet_id: str,
#                                sheet_title: str) -> pd.DataFrame:


# Path: tests/lib/collectors/gsheets.py
import unittest
import mock
from dftimewolf import config
from dftimewolf.lib import errors
from dftimewolf.lib import state
from dftimewolf.lib.collectors import gsheets



# pylint: disable=line-too-long
VALID_SHEET = {'range': 'Sheet1!A1:Z1000', 'majorDimension': 'ROWS', 'values': [
    ['message', 'timestamp', 'datetime', 'timestamp_desc ', 'extra_field_1 ', 'extra_field_2'],
    ['A message', '1331698658276340', '2015-07-24T19:01:01+00:00', 'Write time', 'foo ', 'bar'],
    ['', '1331698658276340', '2016-07-24T19:01:01+00:00', 'creation time', 'foo', ''],
    ['A message', '', '', 'modified time', 'foo', 'bar']]}
# Missing "datetime" columnd
INVALID_SHEET = {'range': 'Sheet2!A1:Y1000', 'majorDimension': 'ROWS', 'values': [
    ['message', 'timestamp', 'timestamp_desc ', 'extra_field_1 ', 'extra_field_2'],
    ['A message', '1331698658276340', 'Write time', 'foo ', 'bar'],
    ['', '1331698658276340', 'creation time', 'foo', ''],
    ['A message', '', 'modified time', 'foo', 'bar']]}
# pylint: enable=line-too-long


class GoogleSheetsCollectorTest(unittest.TestCase):
  """Tests for the Google Sheets collector module ."""

  def testInitialization(self):
    """Tests that the collector can be initialized."""
    test_state = state.DFTimewolfState(config.Config)
    collector = gsheets.GoogleSheetsCollector(test_state)
    self.assertIsNotNone(collector)

  # pylint: disable=protected-access
  def testValidateSpreadSheetId(self):
    """Tests that the collector validate and extract spreadsheet id."""
    test_state = state.DFTimewolfState(config.Config)

    collector = gsheets.GoogleSheetsCollector(test_state)