<UserControl
  x:Class="NuGet.PackageManagement.UI.InfiniteScrollList"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:nuget="clr-namespace:NuGet.PackageManagement.UI"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:vs="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.15.0"
  mc:Ignorable="d"
  d:DesignHeight="200"
  d:DesignWidth="500">
  <UserControl.Resources>
    <nuget:InfiniteScrollListItemStyleSelector
      x:Key="itemStyleSelector" />

    <DataTemplate
      DataType="{x:Type nuget:PackageDependencyMetadata}">
      <TextBlock
        Text="{Binding}" />
    </DataTemplate>

    <DataTemplate
      DataType="{x:Type nuget:PackageItemListViewModel}">
      <nuget:PackageItemControl
        DataContext="{Binding}" />
    </DataTemplate>

    <DataTemplate
      DataType="{x:Type nuget:LoadingStatusIndicator}">
      <Grid
        Margin="0,8">
        <TextBlock
          Name="_noItemsFound"
          FontStyle="Italic"
          HorizontalAlignment="Center"
          Text="{x:Static nuget:Resources.Text_NoPackagesFound}"
          Visibility="Collapsed" />

        <Grid
          Name="_progressBar"
          Visibility="Collapsed"
          HorizontalAlignment="Center"
          Height="22">
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
          </Grid.ColumnDefinitions>
          <nuget:Spinner
            Grid.Column="0"
            Width="16"
            Height="16"
            Margin="3"
            HorizontalAlignment="Center" 
            VerticalAlignment="Center" 
            Visibility="{Binding Visibility,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}, AncestorLevel=1}}"/>
          <TextBlock
            Grid.Column="1"
            Text="{Binding Path=LoadingMessage}"
            HorizontalAlignment="Left" 
            VerticalAlignment="Center"/>
        </Grid>
      </Grid>
      <DataTemplate.Triggers>
        <DataTrigger
          Binding="{Binding Path=Status}"
          Value="Loading">
          <Setter
            TargetName="_progressBar"
            Property="Visibility"
            Value="Visible" />
        </DataTrigger>
        <DataTrigger
          Binding="{Binding Path=Status}"
          Value="Ready">
          <Setter
            TargetName="_progressBar"
            Property="Visibility"
            Value="Visible" />
        </DataTrigger>
        <DataTrigger
          Binding="{Binding Path=Status}"
          Value="NoItemsFound">
          <Setter
            TargetName="_noItemsFound"
            Property="Visibility"
            Value="Visible" />
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>

    <!-- Template used by ListBoxItem that represents a package. -->
    <ControlTemplate
      x:Key="ListBoxItemTemplate"
      TargetType="{x:Type ListBoxItem}">
      <Border
        x:Name="Bd"
        BorderThickness="0"
        Background="{TemplateBinding Background}"
        Padding="0"
        SnapsToDevicePixels="true">
        <ContentPresenter
          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
      </Border>
      <ControlTemplate.Triggers>
        <!-- set the background for IsEnabled == false -->
        <Trigger
          Property="IsEnabled"
          Value="false">
          <Setter
            Property="Background"
            TargetName="Bd"
            Value="{DynamicResource {x:Static nuget:Brushes.ListPaneBackground}}" />
        </Trigger>

        <MultiTrigger>
          <MultiTrigger.Conditions>
            <Condition
              Property="IsMouseOver"
              Value="True" />
          </MultiTrigger.Conditions>
          <Setter
            Property="Background"
            TargetName="Bd"
            Value="{DynamicResource {x:Static nuget:Brushes.ContentMouseOverBrushKey}}" />
          <Setter
            Property="TextBlock.Foreground"
            Value="{DynamicResource {x:Static nuget:Brushes.ContentMouseOverTextBrushKey}}" />
        </MultiTrigger>
        <MultiTrigger>
          <MultiTrigger.Conditions>
            <Condition
              Property="Selector.IsSelectionActive"
              Value="False" />
            <Condition
              Property="IsSelected"
              Value="True" />
          </MultiTrigger.Conditions>
          <Setter
            Property="Background"
            TargetName="Bd"
            Value="{DynamicResource {x:Static nuget:Brushes.ContentInactiveSelectedBrushKey}}" />
          <Setter
            Property="TextBlock.Foreground"
            Value="{DynamicResource {x:Static nuget:Brushes.ContentInactiveSelectedTextBrushKey}}" />
        </MultiTrigger>
        <MultiTrigger>
          <MultiTrigger.Conditions>
            <Condition
              Property="Selector.IsSelectionActive"
              Value="True" />
            <Condition
              Property="IsSelected"
              Value="True" />
          </MultiTrigger.Conditions>
          <Setter
            Property="Background"
            TargetName="Bd"
            Value="{DynamicResource {x:Static nuget:Brushes.ContentSelectedBrushKey}}" />
          <Setter
            Property="TextBlock.Foreground"
            TargetName="Bd"
            Value="{DynamicResource {x:Static nuget:Brushes.ContentSelectedTextBrushKey}}" />
        </MultiTrigger>
      </ControlTemplate.Triggers>
    </ControlTemplate>

    <!-- Template used by the LoadingIndicator. We use it to disable the background change when mouse hovers over it. -->
    <ControlTemplate
      x:Key="LoadingIndicatorListBoxItemTemplate"
      TargetType="{x:Type ListBoxItem}">
      <Border
        x:Name="Bd"
        BorderThickness="0"
        Background="{DynamicResource {x:Static nuget:Brushes.ListPaneBackground}}"
        Padding="0"
        SnapsToDevicePixels="true">
        <ContentPresenter
          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
      </Border>
    </ControlTemplate>

    <!-- the base style of the ListBoxItem. -->
    <Style
      x:Key="listBoxItemStyle"
      TargetType="{x:Type ListBoxItem}">
      <Setter
        Property="Padding"
        Value="0" />
      <Setter
        Property="SnapsToDevicePixels"
        Value="True" />
      <Setter
        Property="HorizontalContentAlignment"
        Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
      <Setter
        Property="VerticalContentAlignment"
        Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
      <Setter
        Property="Background"
        Value="Transparent" />
    </Style>

    <!-- the style of the ListBoxItem when the item is the loading status indicator. -->
    <Style
      x:Key="loadingStatusIndicatorStyle"
      TargetType="{x:Type ListBoxItem}"
      BasedOn="{StaticResource listBoxItemStyle}">
      <Setter
        Property="Template"
        Value="{StaticResource LoadingIndicatorListBoxItemTemplate}" />
      <Setter
        Property="Focusable"
        Value="False" />
    </Style>

    <!-- the style of the ListBoxItem when the item is a package. -->
    <Style
      x:Key="packageItemStyle"
      TargetType="{x:Type ListBoxItem}"
      BasedOn="{StaticResource listBoxItemStyle}">
      <!--
            Note that we cannot set the template property in xaml list this:

               <Setter Property="Template" Value="{StaticResource ListBoxItemTemplate}" />

            The reason is that the template references resources defined in VisualStudio, which are obviously not
            available when this is used in the standalone mode, i.e. outside of VisualStudio. So the setter is
            added by code when Standalone == false.
            -->
    </Style>

    <Style TargetType="FrameworkElement" x:Key="FadeAnimationStyle">
      <Setter Property="Visibility" Value="Hidden"/>
      <Style.Triggers>
        <Trigger Property="Visibility" Value="Visible">
          <Trigger.EnterActions>
            <BeginStoryboard>
              <Storyboard>
                <DoubleAnimation Storyboard.TargetProperty="Opacity"
                             From="0.0" To="1.0" Duration="0:0:0.7"/>
              </Storyboard>
            </BeginStoryboard>
          </Trigger.EnterActions>
        </Trigger>
      </Style.Triggers>
    </Style>
    <!--
      This scrollviewer template has one change from the default - a -22 margin on the verical srollbar.
      This enables the loadingStatusBar to appear to be in the listbox.
    -->
    <ControlTemplate x:Key="ScrollViewerWithScrollBarExtraLargeOnTop" TargetType="{x:Type ScrollViewer}">
      <Grid x:Name="Grid" Background="{TemplateBinding Background}" >
          <Grid.ColumnDefinitions>
              <ColumnDefinition Width="*"/>
              <ColumnDefinition Width="Auto"/>
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
              <RowDefinition Height="*"/>
              <RowDefinition Height="Auto"/>
          </Grid.RowDefinitions>
          <Rectangle x:Name="Corner" Grid.Column="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Row="1"/>
          <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
          <ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Margin="0,-22,0,0" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
          <ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
      </Grid>
    </ControlTemplate>
  </UserControl.Resources>
  <DockPanel LastChildFill="True">
    <Border
      x:Name="_updateButtonContainer"
      DockPanel.Dock="Top"
      BorderBrush="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}"
      BorderThickness="0,0,0,1"
      Background="{DynamicResource {x:Static nuget:Brushes.LegalMessageBackground}}"
      Visibility="Collapsed">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="auto" />
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="auto" />
        </Grid.ColumnDefinitions>
        <CheckBox
          x:Name="_selectAllPackages"
          Grid.Column="0"
          Margin="4, 8"
          VerticalAlignment="Center"
          Checked="SelectAllPackagesCheckBox_Checked"
          Unchecked="SelectAllPackagesCheckBox_Unchecked"
          Foreground="{DynamicResource {x:Static nuget:Brushes.UIText}}"
          Content="{x:Static nuget:Resources.Checkbox_SelectAllPackages}" />
        <Button
          x:Name="_updateButton"
          Grid.Column="2"
          MinWidth="100"
          MinHeight="24"
          Margin="24,8"
          VerticalAlignment="Center"
          Click="_updateButton_Click"
          Content="{x:Static nuget:Resources.Button_Update}" />
      </Grid>
    </Border>
    <Grid
      DockPanel.Dock="Top"
      Background="{DynamicResource {x:Static nuget:Brushes.ListPaneBackground}}"
      Height="22">
      <nuget:LoadingStatusBar 
        x:Name="_loadingStatusBar"
        ShowMoreResultsClick="_loadingStatusBar_ShowMoreResultsClick"
        DismissClick="_loadingStatusBar_DismissClick"
        Style="{StaticResource FadeAnimationStyle}"
        Visibility="Hidden"/>
      <!--
        Special TextBlock to report loading status to assistive technologies (narrator).
        Code behind changes to the Text property will trigger a narrator event.
      -->
      <vs:LiveTextBlock
        x:Name="_ltbLoading"
        Visibility="Collapsed"
        IsFrequencyLimited="True"
        Focusable="False"
        AutomationProperties.IsOffscreenBehavior="Offscreen" />
    </Grid>
    <nuget:InfiniteScrollListBox
      d:DataContext="{d:DesignData Source=/Design/PackageItemListViewSampleData.xaml,IsDesignTimeCreatable=True}"
      x:Name="_list"
      AutomationProperties.Name="{x:Static nuget:Resources.Accessibility_Packages}"
      DockPanel.Dock="Bottom"
      PreviewKeyUp="List_PreviewKeyUp"
      Background="{DynamicResource {x:Static nuget:Brushes.ListPaneBackground}}"
      Foreground="{DynamicResource {x:Static nuget:Brushes.UIText}}"
      ScrollViewer.HorizontalScrollBarVisibility="Disabled"
      ScrollViewer.VerticalScrollBarVisibility="Visible"
      ItemContainerStyleSelector="{DynamicResource itemStyleSelector}"
      VirtualizingPanel.IsVirtualizing="true"
      VirtualizingPanel.VirtualizationMode="Recycling"
      VirtualizingPanel.CacheLength="1,2"
      VirtualizingPanel.CacheLengthUnit="Page"
      BorderThickness="0,0,0,0"
      HorizontalContentAlignment="Stretch"
      SelectionChanged="List_SelectionChanged"
      Loaded="List_Loaded"
      ItemsSource="{Binding}">
      <!-- set the template to disable the background change when the IsEnabled is false. -->
      <ListBox.Template>
        <ControlTemplate
          TargetType="{x:Type ListBox}">
          <Border
            x:Name="Bd"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="{TemplateBinding Background}"
            Padding="1"
            SnapsToDevicePixels="true">
            <ScrollViewer
              Template="{StaticResource ScrollViewerWithScrollBarExtraLargeOnTop}"
              Focusable="false"
              Padding="{TemplateBinding Padding}">
              <ItemsPresenter
                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
            </ScrollViewer>
          </Border>
        </ControlTemplate>
      </ListBox.Template>
    </nuget:InfiniteScrollListBox>
  </DockPanel>
</UserControl>
