Attribute VB_Name = "MainImpl"
Option Private Module
Option Explicit

Public Function ClearData()
  ThisWorkbook.Sheets(SHT_START).Range("I3:I16") = vbNullString
  ThisWorkbook.Sheets(SHT_START).Range("L3:L8") = vbNullString
  ThisWorkbook.Sheets(SHT_DOCS).UsedRange.Offset(1).ClearContents
  ThisWorkbook.Sheets(SHT_IGNORE).UsedRange.Offset(1).ClearContents
  ThisWorkbook.Sheets(SHT_LINKS).UsedRange.Offset(1).ClearContents
  
  ThisWorkbook.Names(VIEW_CELL_HASH).RefersToRange = ""
  ThisWorkbook.Names(VIEW_CELL_UPDATE).RefersToRange = ""
  ThisWorkbook.Names(VIEW_CELL_LAWS).RefersToRange = ""
End Function

Public Function ClearQueryDocs()
  ThisWorkbook.Sheets(SHT_OUT_DOCS).UsedRange.Offset(1).ClearContents
End Function

Public Function ClearQueryLinks()
  ThisWorkbook.Sheets(SHT_OUT_LINKS).UsedRange.Offset(1).ClearContents
End Function

Public Function ImportData(iSource As InfoDatabase, iDestination As InfoDatabase)
  Call iDestination.StartOptimization
  
  Dim importer As New DataImporter: Call importer.Init(iDestination, DoIncludeTBALinks)
  
  Call CSE_ProgressBar.Init("Загрузка данных", maxVal:=DOCS_PROGRESS_FACTOR * iSource.Count + iSource.CountLinks)
  Call CSE_ProgressBar.InitSecondBar(maxVal:=iSource.Count)
  CSE_ProgressBar.Description = "Список документов"
  Call CSE_ProgressBar.ShowModeless
  
  Call importer.LoadDocs(iSource.Laws)
  
  CSE_ProgressBar.Description = "Список связей"
  Call CSE_ProgressBar.InitSecondBar(maxVal:=iSource.CountLinks)
  
  Call importer.LoadLinks(iSource.Links)
  Unload CSE_ProgressBar
  
  ThisWorkbook.Names(VIEW_CELL_HASH).RefersToRange = iSource.Hash
  ThisWorkbook.Names(VIEW_CELL_UPDATE).RefersToRange = Now()
  ThisWorkbook.Names(VIEW_CELL_LAWS).RefersToRange = iSource.docsLocation_
  
  Call iDestination.EndOptimization
End Function

Public Function ProposeNewDocument(target As Word.Document, theDB As InfoDatabase) As Boolean
  ProposeNewDocument = False
  
  If Not CheckProposedDocument(target, theDB) Then _
    Exit Function
  
  Dim sName$: sName = VBA.Left(target.Name, VBA.InStr(target.Name, ".")) & "docx"
  Dim dbFolder$: dbFolder = theDB.docsLocation_ & "\Входящие\"
  Dim fso As New Scripting.FileSystemObject
  If fso.FileExists(dbFolder & sName) Then
    Call UserInteraction.ShowMessage(EN_FILE_EXISTS)
    Exit Function
  End If
  
  If Not fso.FolderExists(dbFolder) Then _
    Call MkDir(dbFolder)
  Call target.SaveAs(dbFolder & sName, FileFormat:=wdFormatDocumentDefault)
  ProposeNewDocument = True
End Function

Public Function Output2Excel(outWB As Excel.Workbook, theDB As InfoDatabase)
  Dim exporter As New ActiveStateExporter: Call exporter.Init(outWB, theDB)
  
  Dim lawIDs As New Scripting.Dictionary
  Set lawIDs = exporter.ExportLaws()
  
  Call CSE_ProgressBar.InitSecondBar(maxVal:=theDB.CountLinks)
  CSE_ProgressBar.Description = "Список связей"
  
  Call exporter.ExportLinks(lawIDs)
End Function

Public Function LoadTextsForLinks(iSource As InfoDatabase, iDestination As Excel.Worksheet)
  Dim iLoaded As New Scripting.Dictionary
  Dim nRow&: nRow = HT03_DEFAULT_FIRST_LINE
  Do While iDestination.Cells(nRow, S_QL_SOURCE_ID) <> vbNullString
    Dim iLaw As IteratorLaw: Set iLaw = iSource.Data(iDestination.Cells(nRow, S_QL_SOURCE_ID))
    If Not iLaw Is Nothing Then
      iDestination.Cells(nRow, S_QL_SOURCE_TITLE) = iLaw.Title
      If Not iLoaded.Exists(iLaw.ID) Then
        Call iLoaded.Add(iLaw.ID, 0)
        Call LoadLawLinks(iLaw, iSource, iDestination)
      End If
    End If
    
    Set iLaw = iSource.Data(iDestination.Cells(nRow, S_QL_TARGET_ID))
    If Not iLaw Is Nothing Then
      iDestination.Cells(nRow, S_QL_TARGET_TITLE) = iLaw.Title
      If Not iLoaded.Exists(iLaw.ID) Then
        Call iLoaded.Add(iLaw.ID, 0)
        Call LoadLawLinks(iLaw, iSource, iDestination)
      End If
    End If
    
    nRow = nRow + 1
    Call CSE_ProgressBar.IncrementA
    
    DoEvents
    If CSE_ProgressBar.Interrupted Then _
      Exit Function
  Loop
End Function

Public Function GraphExpandOnce(ByRef target As Scripting.Dictionary, lnkType As TQueryLink, lnkDir As TLinkDirection)
  Dim linkFilter As New QFilterLinkType: Call linkFilter.Init(g_UIState.linkType_)
  Dim theGraph As CDS_Graph: Set theGraph = CreateGraph(linkFilter)
  Select Case lnkDir
    Case T_LD_STRAIGHT: Call theGraph.ExpandOutsOnce(target)
    Case T_LD_REVERSE: Call theGraph.ExpandInsOnce(target)
    Case T_LD_BOTH: Call theGraph.ExpandBiderctionalOnce(target)
  End Select
End Function

Public Function GraphExpandFull(ByRef target As Scripting.Dictionary, lnkType As TQueryLink, lnkDir As TLinkDirection)
  Dim linkFilter As New QFilterLinkType: Call linkFilter.Init(g_UIState.linkType_)
  Dim theGraph As CDS_Graph: Set theGraph = CreateGraph(linkFilter)
  Select Case lnkDir
    Case T_LD_STRAIGHT: Call theGraph.ExpandOutputs(target)
    Case T_LD_REVERSE: Call theGraph.ExpandInputs(target)
    Case T_LD_BOTH: Call theGraph.ExpandBiderctional(target)
  End Select
End Function

' ===========
Private Function CheckProposedDocument(target As Word.Document, localData As InfoDatabase) As Boolean
  Dim iDoc As New InfoDocument
  If Not iDoc.Init(target) Then
    CheckProposedDocument = True
    Exit Function
  End If
  
  Dim docIter As ItemCachedLaw: Set docIter = localData.Cache(iDoc.gid_)
  If Not docIter Is Nothing Then
    If docIter.status_ = T_LAWS_OUTER Then
      CheckProposedDocument = True
      Exit Function
    End If
  End If
  If Not localData.FindByFileName(target.Name) Is Nothing Then
    Call UserInteraction.ShowMessage(EM_FILENAME_TAKEN)
    CheckProposedDocument = False
    Exit Function
  End If
    
  If localData.Contains(iDoc.gid_) Then
    If localData.Data(iDoc.gid_).FileName <> HT03_FILE_NOT_LOADED Then
      Call UserInteraction.ShowMessage(EM_ID_TAKEN)
      CheckProposedDocument = False
      Exit Function
    End If
  End If
  
  CheckProposedDocument = True
End Function

Private Function IsDefaultBookmark(sBookmark$) As Boolean
  IsDefaultBookmark = sBookmark = vbNullString Or sBookmark = "sub_0"
End Function

Private Function LoadLawLinks(iLaw As IteratorLaw, iSource As InfoDatabase, iDestination As Excel.Worksheet)
  Dim wordApp As New API_WordWrapper
  Call wordApp.CreateApplication(bIsVisible:=False)
  
  Dim sourceDoc As Word.Document: Set sourceDoc = wordApp.OpenDocument(iSource.DocumentsRelativePath & iLaw.FileName, bReadOnly:=True)
  If sourceDoc Is Nothing Then
    Call wordApp.ReleaseApplication
    Exit Function
  End If
  
  CSE_ProgressBar.DescriptionTB = wordApp.Document.Name
  Dim gid&: gid = iLaw.ID
  Dim nRow&: nRow = HT03_DEFAULT_FIRST_LINE
  Do While iDestination.Cells(nRow, 1) <> vbNullString
    If iDestination.Cells(nRow, S_QL_SOURCE_ID) = gid Then
      Dim subSource$: subSource = iDestination.Cells(nRow, S_QL_SOURCE_SUB)
      If IsDefaultBookmark(subSource) Or Not sourceDoc.Bookmarks.Exists(subSource) Then
        iDestination.Cells(nRow, S_QL_SOURCE_TEXT) = iLaw.Title
      Else
        iDestination.Cells(nRow, S_QL_SOURCE_TEXT) = sourceDoc.Bookmarks(subSource).Range.Text
      End If
    End If
    
    If iDestination.Cells(nRow, S_QL_TARGET_ID) = gid Then
      Dim subDest$: subDest = iDestination.Cells(nRow, S_QL_TARGET_SUB)
      If IsDefaultBookmark(subDest) Or Not sourceDoc.Bookmarks.Exists(subDest) Then
        iDestination.Cells(nRow, S_QL_TARGET_TEXT) = iLaw.Title
      Else
        iDestination.Cells(nRow, S_QL_TARGET_TEXT) = sourceDoc.Bookmarks(subDest).Range.Text
      End If
    End If
    nRow = nRow + 1
  Loop
  
  Call wordApp.ReleaseDocument
  Call wordApp.ReleaseApplication
End Function
