Imports System.Collections.ObjectModel
Imports System.Drawing.Printing
Imports ThinkGeo.Core
Imports ThinkGeo.UI.WinForms

Public Class CreatePageLayout

  Private moRoadsLayer As ShapeFileFeatureLayer
  Private moHydroLayer As ShapeFileFeatureLayer
  Private moPolyLayer As ShapeFileFeatureLayer
  Private moFeatureExtent As RectangleShape
  Private moStyle1 As AreaStyle = AreaStyle.CreateSimpleAreaStyle(GeoColors.Blue, GeoColors.Black, 6)
  Private moStyle2 As AreaStyle = AreaStyle.CreateSimpleAreaStyle(GeoColors.Red, GeoColors.Black, 6)
  Private mbStyle1 As Boolean = True
  Private Shared msPdfFileName As String = String.Empty
  Private Shared msFlagFilePath As String = String.Empty
  Private Shared msPdfSyncFileName As String = String.Empty
  Private Shared msGeoEncode As String = String.Empty
  Public Property PageLayout As MapView

  Public Enum EnumPagePosition
      TopLeft = 1
      TopRight = 2
      LowerLeft = 3
      LowerRight = 4
    End Enum
    Public Enum EnumCenterType
      Horizontal = 1
      Vertical = 2
    End Enum
  Private Sub AddStockTextWrapLabel()
    Dim oLabelPrinterLayer As LabelPrinterLayer = New LabelPrinterLayer()
    Dim oPageBoundingbox As RectangleShape

    '***** Setup the text and the font..
    With oLabelPrinterLayer
      .Text = "This is a long text to demonstrate the word wrapping problem when using the built-in word wrapping capability provided by LabelPrinterLayer. Note that the first line is indented, even though we don't want that. However, when you print to PDF the text wrapping in the PDF matches."
      .Font = New GeoFont("Arial", 10, DrawingFontStyles.Regular)
      .TextBrush = New GeoSolidBrush(GeoColors.Black)

      '***** Set the labels position so that is it centered on the page one inch from the top                        
      oPageBoundingbox = GetPageBoundingBox(PrintingUnit.Inch)
      Dim oLabelCenter As PointShape = New PointShape()
      oLabelCenter.X = oPageBoundingbox.UpperRightPoint.X - oPageBoundingbox.Width / 2
      oLabelCenter.Y = oPageBoundingbox.UpperLeftPoint.Y - 0.75

      .PrinterWrapMode = PrinterWrapMode.WrapText
      .ResizeMode = PrinterResizeMode.Resizable
      .SetPosition(5, 0.75, oLabelCenter, PrintingUnit.Inch)
    End With
    Dim oPrinterOverlay As PrinterInteractiveOverlay = mGetPrinterOverlay()
    oPrinterOverlay.PrinterLayers.Add(Guid.NewGuid.ToString, oLabelPrinterLayer)

  End Sub
  Private Sub mAddScaleLine()
    Dim oScaleLine As New ScaleLinePrinterLayer(moMapPrinterLayer)

    With oScaleLine
      .DragMode = PrinterDragMode.Draggable
      .MapUnit = moMapPrinterLayer.MapUnit
      .Name = "ScaleLine"
      .Pen = GeoPens.Black
      .ResizeMode = PrinterResizeMode.Resizable
      .TextStyle = New TextStyle("", New GeoFont("Century Gothic", 12, DrawingFontStyles.Regular), GeoBrushes.Black)
      .UnitSystem = ScaleLineUnitSystem.NauticalMileAndImperial
      .SetPosition(4, 0.75, -2, 1, PrintingUnit.Inch)
    End With
    Dim oPrinterOverlay As PrinterInteractiveOverlay = mGetPrinterOverlay()
    oPrinterOverlay.PrinterLayers.Add(Guid.NewGuid.ToString, oScaleLine)

  End Sub
  'Private Sub AddCustomTextWrapLabel()
  '  Dim oLabelPrinterLayer As LabelPrinterLayer = New CustomLabelPrinterLayer()
  '  Dim oPageBoundingbox As RectangleShape

  '  '***** Setup the text and the font..
  '  With oLabelPrinterLayer
  '    .Text = "This is a long text to demonstrate the word wrapping problem when using the custom word wrapping capability. Everything looks good until you print to PDF. The text wrapping in the PDF is not the same as in the CustomLablePrinterLayer."
  '    .Font = New GeoFont("Arial", 10, DrawingFontStyles.Regular)
  '    .TextBrush = New GeoSolidBrush(GeoColor.StandardColors.Black)

  '    '***** Set the labels position so that is it centered on the page one inch from the top                        
  '    oPageBoundingbox = GetPageBoundingBox(PrintingUnit.Inch)
  '    Dim oLabelCenter As PointShape = New PointShape()
  '    oLabelCenter.X = oPageBoundingbox.UpperRightPoint.X - oPageBoundingbox.Width / 2
  '    oLabelCenter.Y = oPageBoundingbox.UpperLeftPoint.Y - 2

  '    .PrinterWrapMode = PrinterWrapMode.WrapText
  '    .ResizeMode = PrinterResizeMode.Resizable
  '    .SetPosition(5, 0.75, oLabelCenter, PrintingUnit.Inch)
  '  End With
  '  Dim oPrinterOverlay As PrinterInteractiveOverlay = mGetPrinterOverlay()
  '  oPrinterOverlay.PrinterLayers.Add(Guid.NewGuid.ToString, oLabelPrinterLayer)

  'End Sub

  Public Sub New(oMap As MapView)
    PageLayout = oMap
    ZoomLevelHelper.InitZoomLevels()
    CreateDefaultLayout()

    'ZoomLevelHelper.ApplyCustomZoomLevels(MainMap.ZoomLevelSet, ZoomLevelHelper.EnumSymbolType.None)

  End Sub
  Private moPrinterOverlay As PrinterInteractiveOverlay
  Private moPrinterPage As PagePrinterLayer
  Private moMapPrinterLayer As MapPrinterLayer
  Public Async Sub CreateDefaultLayout()
    Dim oExtentRectangle As RectangleShape
    Dim dScale As Double
    moPrinterOverlay = New PrinterInteractiveOverlay()
    With PageLayout
      '***** Setup the map unit, you want to always use feet or meters for printer layout maps
      .MapUnit = GeographyUnit.Feet
      '***** Create the default zoom levels for the layout map
      .ZoomLevelSet = New PrinterZoomLevelSet(.MapUnit, PrinterHelper.GetPointsPerGeographyUnit(.MapUnit))

      '***** Set the background color to gray so there is contrast with the white page
      .BackgroundOverlay.BackgroundBrush = New GeoSolidBrush(GeoColors.LightGray)

      '***** Create the PrinterInteractiveOverlay to contain all of the PrinterLayers.
      '***** The interactive overlay allows the layers to be interacted with
      .InteractiveOverlays.Add("PrinterOverlay", moPrinterOverlay)
      .InteractiveOverlays.MoveToBottom("PrinterOverlay")

      '***** Create the PagePrinterLayer which shows the page boundary and 
      '***** is the area the user will arrange all of the other layers on top of.
      moPrinterPage = New PagePrinterLayer()
      With moPrinterPage
        .Open()
        .BackgroundMask = AreaStyle.CreateSimpleAreaStyle(GeoColors.White, GeoColors.Black, 1)
        moPrinterOverlay.PrinterLayers.Add("PrinterPage", moPrinterPage)
        '***** Get the page's extent, scale it up by 10%
        oExtentRectangle = CType(RectangleShape.ScaleUp(.GetPosition(), 10), RectangleShape)
        '***** Set oExtentRectangle as the default current extent
      End With
      .CurrentExtent = oExtentRectangle

      '***** Set the minimum scale of the map to the last zoom level
      .MinimumScale = .ZoomLevelSet.ZoomLevel20.Scale

      'AddStockTextWrapLabel()
      'AddCustomTextWrapLabel()
      'mAddMapLayer()
      mAddGdalMapLayer()
      mAddScaleLine()

      Await PageLayout.RefreshAsync

      dScale = mGetScale()
    End With
  End Sub
  Private Sub mAddMapLayer()
    Dim moShapefile = New CustomShapefile("..\..\Data\States_Albers.shp")
    Dim oAreaStyle1 As AreaStyle = AreaStyle.CreateSimpleAreaStyle(GeoColors.Transparent, GeoColors.Blue, 1)
    Dim oAreaStyle2 As AreaStyle = AreaStyle.CreateSimpleAreaStyle(GeoColors.Transparent, GeoColors.Red, 1)
    ZoomLevelHelper.ApplyCustomZoomLevels(moShapefile.ZoomLevelSet, ZoomLevelHelper.EnumSymbolType.AreaSymbol)
    'ZoomLevelHelper.ApplyCustomZoomLevels(moSelectionLayer.ZoomLevelSet, ZoomLevelHelper.EnumSymbolType.AreaSymbol)

    Dim iFirstHalf As Integer = 20
    Dim iSecondHalf = 38
    Dim iCounter As Integer = 0

    For Each oZoomLevel As ZoomLevel In moShapefile.ZoomLevelSet.CustomZoomLevels
      If iCounter < 20 Then
        oZoomLevel.DefaultAreaStyle = oAreaStyle1
      Else
        oZoomLevel.DefaultAreaStyle = oAreaStyle2
      End If
      iCounter = iCounter + 1
    Next oZoomLevel
    'moShapefile.DrawingQuality = DrawingQuality.HighSpeed
    Dim oProj As New ProjectionConverter(102003, 3857)
    'moShapefile.FeatureSource.ProjectionConverter = oProj

    'Dim oSelectionStyle As AreaStyle = AreaStyle.CreateSimpleAreaStyle(GeoColors.LightGray, GeoColors.DimGray, 3)
    'For Each oZoomLevel As ZoomLevel In moSelectionLayer.ZoomLevelSet.CustomZoomLevels
    '  oZoomLevel.DefaultAreaStyle = oSelectionStyle
    'Next oZoomLevel

    'moShapefile.SelectionLayer = moSelectionLayer


    'Dim oOverlay As New PrinterInteractiveOverlay() With {.Name = "PrinterOverlay"}
    'PageLayout.Overlays.Add("PrinterOverlay", moprinterOverlay)
    'Dim oOverlay = CType(MainMap.Overlays("Layers"), LayerOverlay)
    'oOverlay.Layers.Add(moShapefile)
    moMapPrinterLayer = New MapPrinterLayer()
    moMapPrinterLayer.MapUnit = GeographyUnit.Meter
    Dim oLayerExtent As RectangleShape = moPrinterPage.GetBoundingBox
    oLayerExtent.ScaleDown(10)
    moMapPrinterLayer.SetPosition(oLayerExtent)

    moMapPrinterLayer.Layers.Add(moShapefile)
    moShapefile.Open()
    moPrinterOverlay.PrinterLayers.Add(moMapPrinterLayer)
    moMapPrinterLayer.MapExtent = moShapefile.GetBoundingBox
    Dim dScale = mGetScale()
  End Sub
  Private Sub mAddGdalMapLayer()
    Dim moShapefile = New GdalFeatureLayer("..\..\Data\BC_Mch.shp", "BC_Mch")
    Dim oAreaStyle1 As AreaStyle = AreaStyle.CreateSimpleAreaStyle(GeoColors.Transparent, GeoColors.Blue, 1)
    Dim oAreaStyle2 As AreaStyle = AreaStyle.CreateSimpleAreaStyle(GeoColors.Transparent, GeoColors.Red, 1)
    ZoomLevelHelper.ApplyCustomZoomLevels(moShapefile.ZoomLevelSet, ZoomLevelHelper.EnumSymbolType.AreaSymbol)
    'ZoomLevelHelper.ApplyCustomZoomLevels(moSelectionLayer.ZoomLevelSet, ZoomLevelHelper.EnumSymbolType.AreaSymbol)

    Dim iFirstHalf As Integer = 20
    Dim iSecondHalf = 38
    Dim iCounter As Integer = 0

    For Each oZoomLevel As ZoomLevel In moShapefile.ZoomLevelSet.CustomZoomLevels
      If iCounter < 20 Then
        oZoomLevel.DefaultAreaStyle = oAreaStyle1
      Else
        oZoomLevel.DefaultAreaStyle = oAreaStyle2
      End If
      iCounter = iCounter + 1
    Next oZoomLevel
    'moShapefile.DrawingQuality = DrawingQuality.HighSpeed
    Dim oProj As New ProjectionConverter(102003, 3857)
    'moShapefile.FeatureSource.ProjectionConverter = oProj

    'Dim oSelectionStyle As AreaStyle = AreaStyle.CreateSimpleAreaStyle(GeoColors.LightGray, GeoColors.DimGray, 3)
    'For Each oZoomLevel As ZoomLevel In moSelectionLayer.ZoomLevelSet.CustomZoomLevels
    '  oZoomLevel.DefaultAreaStyle = oSelectionStyle
    'Next oZoomLevel

    'moShapefile.SelectionLayer = moSelectionLayer


    'Dim oOverlay As New PrinterInteractiveOverlay() With {.Name = "PrinterOverlay"}
    'PageLayout.Overlays.Add("PrinterOverlay", moprinterOverlay)
    'Dim oOverlay = CType(MainMap.Overlays("Layers"), LayerOverlay)
    'oOverlay.Layers.Add(moShapefile)
    moMapPrinterLayer = New MapPrinterLayer()
    moMapPrinterLayer.MapUnit = GeographyUnit.Meter

    Dim oLayerExtent As RectangleShape = moPrinterPage.GetBoundingBox
    oLayerExtent.ScaleDown(10)
    moMapPrinterLayer.SetPosition(oLayerExtent)

    moMapPrinterLayer.Layers.Add(moShapefile)
    moShapefile.Open()


    Dim oDataTable As DataTable = moShapefile.QueryTools.ExecuteQuery("SELECT MAX(Age), Min(Age), Count(Age) FROM BC_Mch")


    moPrinterOverlay.PrinterLayers.Add(moMapPrinterLayer)
    moMapPrinterLayer.MapExtent = moShapefile.GetBoundingBox
    Dim dScale = mGetScale()
  End Sub

  Private Function mGetScale() As Double
    With moMapPrinterLayer
      .Open()
      Dim dWidth As Single = CSng(.GetPosition().Width)
      Dim dHeight As Single = CSng(.GetPosition().Height)
      Return MapUtil.GetScale(.MapExtent, dWidth, .MapUnit)
    End With
  End Function
  Private Function GetPageBoundingBox(ByVal unit As PrintingUnit) As RectangleShape
    Dim moPrinterPage As PagePrinterLayer = mGetPrinterPage()
    Return moPrinterPage.GetPosition(unit)
  End Function

  Private Sub mRefreshMapLayers(moPageLayoutMap As MapPrinterLayer)
      If Not moPageLayoutMap Is Nothing Then
        moPageLayoutMap.IsDrawing = True
        ''moPageLayoutMap.ClearCache()
      End If

      PageLayout.Refresh()

      If Not moPageLayoutMap Is Nothing Then
        moPageLayoutMap.IsDrawing = False
      End If
    End Sub

  Private Function mGetPrinterOverlay() As PrinterInteractiveOverlay
    For Each oPrinterOverlay In PageLayout.InteractiveOverlays
      If TypeOf oPrinterOverlay Is PrinterInteractiveOverlay Then
        Return CType(oPrinterOverlay, PrinterInteractiveOverlay)
      End If
    Next oPrinterOverlay
    Return Nothing
  End Function
  Private Function mGetPageLayoutMap(sMapName As String) As MapPrinterLayer
      Dim oPrinterOverlay As PrinterInteractiveOverlay = mGetPrinterOverlay()
      Dim oPrinterLayer As PrinterLayer
      For Each oPrinterLayer In oPrinterOverlay.PrinterLayers
        If TypeOf oPrinterLayer Is MapPrinterLayer AndAlso oPrinterLayer.Name = sMapName Then
          Return CType(oPrinterLayer, MapPrinterLayer)
        End If
      Next oPrinterLayer
      Return Nothing
    End Function
    Private Function mGetPrinterPage() As PagePrinterLayer
      Dim oPrinterOverlay As PrinterInteractiveOverlay = mGetPrinterOverlay()
      Dim oPrinterLayer As PrinterLayer
      For Each oPrinterLayer In oPrinterOverlay.PrinterLayers
        If TypeOf oPrinterLayer Is PagePrinterLayer Then
          Return CType(oPrinterLayer, PagePrinterLayer)
        End If
      Next oPrinterLayer
      Return Nothing
    End Function

    Public Shared Function GetPrinter() As PrinterSettings
      Dim oPrintDialog As New PrintDialog
      Dim oPrinterSettings As PrinterSettings = Nothing

      With oPrintDialog
        If Not .ShowDialog() = DialogResult.Cancel Then
          oPrinterSettings = .PrinterSettings
        End If
      End With
      Return oPrinterSettings
    End Function
    Public Sub Print()

      '***** Get the printer for printing
      Dim oPrinterSettings As PrinterSettings = GetPrinter()
      If oPrinterSettings Is Nothing Then
        Return
      End If

      Dim oPrinterOverLay As PrinterInteractiveOverlay = mGetPrinterOverlay()
      Dim oPagePrinterLayer As PagePrinterLayer = mGetPrinterPage()

      Dim oPrintDocument As New PrintDocument()
      With oPrintDocument
        .PrinterSettings = oPrinterSettings
        .DefaultPageSettings.Landscape = True
        If oPagePrinterLayer.Orientation = PrinterOrientation.Portrait Then
          .DefaultPageSettings.Landscape = False
        End If
        .DefaultPageSettings.PaperSize = New PaperSize("AnsiA", CInt(850), CInt(1100))
      End With

      Dim oRect As RectangleShape
      Dim oNewUpperLeft As PointShape
      Dim oNewLowerRight As PointShape
      Dim oNewRect As RectangleShape

      Dim oPrinterCanvas As PrinterGeoCanvas = New PrinterGeoCanvas()

      '***** Create a rectangle to represent the drawing area for the document
      oPrinterCanvas.DrawingArea = New Rectangle(0, 0, 850, 1100)

      '***** Start the drawing process
      oPrinterCanvas.BeginDrawing(oPrintDocument, oPagePrinterLayer.GetBoundingBox(), PageLayout.MapUnit)

      '***** Loop through all of the PrintingLayers in the PrinterInteractiveOverlay 
      '***** and print all of the except for the PagePrinterLayer                
      Dim labelsInAllLayers As Collection(Of SimpleCandidate) = New Collection(Of SimpleCandidate)()
      For Each oPrinterLayer As PrinterLayer In oPrinterOverLay.PrinterLayers
        oPrinterLayer.IsDrawing = True
        If Not (TypeOf oPrinterLayer Is PagePrinterLayer) Then
          oPrinterLayer.Open()
          '***** Shift the PrinterLayer to the right and up by HardMarginX and HardMarginY
          oRect = (oPrinterLayer.GetPosition(PrintingUnit.Inch))
          oNewUpperLeft = New PointShape(oRect.UpperLeftPoint.X - 0.13, oRect.UpperLeftPoint.Y + 0.06)
          oNewLowerRight = New PointShape(oRect.LowerRightPoint.X - 0.13, oRect.LowerRightPoint.Y + 0.06)
          oNewRect = (New RectangleShape(oNewUpperLeft, oNewLowerRight))
          oPrinterLayer.SetPosition(oNewRect, PrintingUnit.Inch)
          oPrinterLayer.Draw(oPrinterCanvas, labelsInAllLayers)
          oPrinterLayer.SetPosition(oRect, PrintingUnit.Inch)
        End If
        oPrinterLayer.IsDrawing = False
      Next oPrinterLayer

      oPrinterCanvas.EndDrawing()
    End Sub

  'Private Sub btnPrint_Click(sender As System.Object, e As System.EventArgs) Handles btnPrint.Click
  '  btnPrint.Enabled = False
  '  Print()
  '  btnPrint.Enabled = True
  'End Sub

End Class

