<UserControl xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:vm="using:DodoSSH.Client.Shell.ViewModels"
             xmlns:views="using:DodoSSH.Client.App.Views"
             x:Class="DodoSSH.Client.App.Views.HostsScreen"
             x:DataType="vm:MainWindowViewModel">

  <!--
    The hosts screen: the list of machines, and what this application has to say about the one that is
    selected.

    It used to be the list beside a terminal, and the terminal is no longer here. The tab strip is above
    every screen now, so a terminal is a surface the whole window switches to rather than a column on this
    one — see MainWindowViewModel.ShellSurface. What that leaves this screen is the thing its name always
    promised: an overview.

    In its own file, rather than left in MainWindow.axaml, because nothing inside that window can be laid
    out by a test — WebView2's adapter refuses the headless session's thread — so markup that stays there
    is markup nobody can measure. The four blocks in the right column are exactly the ones that most needed
    measuring: two host key prompts and a conflict log, all three of which appear only in states a person
    has to reproduce by hand.

    Its data context is the shell, not the vault, so that the sidebar can be handed the vault and everything
    else can bind Vault.* — the same split MainWindow.axaml had. See MainWindow.axaml's own note on why the
    two cannot be put on one element.
  -->

  <Grid ColumnDefinitions="268,*">

    <views:HostSidebar Grid.Column="0" x:Name="Sidebar" DataContext="{Binding Vault}" />

    <Grid Grid.Column="1" RowDefinitions="Auto,Auto,*,Auto">

      <!--
        Connecting. A password box only for a host that asks to be — a host bound to a stored credential or
        a key wants nothing typed here — and a sentence in its place when it does not, because "nothing
        needs typing" and "something needs typing and the box has not appeared yet" look identical and only
        one of them is fine.
      -->
      <Border Grid.Row="0" Padding="12,8" Background="{StaticResource Panel}"
              BorderBrush="{StaticResource BorderSubtle}" BorderThickness="0,0,0,1">
        <StackPanel Orientation="Horizontal" Spacing="8">
          <TextBox Text="{Binding Vault.ConnectPassword}" PlaceholderText="password (not stored)"
                   PasswordChar="•" Width="200" VerticalAlignment="Center"
                   IsVisible="{Binding Vault.SelectedHostAsksForAPassword}"
                   ToolTip.Tip="Typed each time and never stored. To stop typing it, add a password under Keychain and bind this host to it in the host's own editor." />
          <TextBlock Text="{Binding Vault.SelectedHostAuthenticationNote}" Classes="hint"
                     FontSize="11" VerticalAlignment="Center"
                     IsVisible="{Binding !Vault.SelectedHostAsksForAPassword}" />
          <Button Classes="accent" Content="CONNECT" Command="{Binding Vault.ConnectCommand}"
                  IsEnabled="{Binding !Vault.IsBusy}" />
        </StackPanel>
      </Border>

      <StackPanel Grid.Row="1">

        <!--
          Host key prompts. Unknown and changed look deliberately different: one is a decision, the other is
          a refusal. Presenting a changed key with a "continue" button is how users are taught to click
          through the one warning that matters.
        -->
        <Border Padding="12,10" Background="{StaticResource WarnWash}"
                BorderBrush="{StaticResource WarnSoft}" BorderThickness="0,0,0,1"
                IsVisible="{Binding Vault.HasPendingHostKey}">
          <StackPanel Spacing="6">
            <TextBlock Text="This host has not been seen before. Check the fingerprint against what the server's operator published."
                       Foreground="{StaticResource WarnText}" TextWrapping="Wrap" />
            <SelectableTextBlock Classes="mono" Text="{Binding Vault.PendingHostKey.Fingerprint}"
                                 Foreground="{StaticResource Warn}" TextWrapping="Wrap" />
            <StackPanel Orientation="Horizontal" Spacing="8">
              <Button Classes="accent" Content="TRUST AND CONNECT"
                      Command="{Binding Vault.TrustHostKeyCommand}" />
              <Button Classes="ghost" Content="CANCEL"
                      Command="{Binding Vault.RejectHostKeyCommand}" />
            </StackPanel>
          </StackPanel>
        </Border>

        <Border Padding="12,10" Background="{StaticResource DangerWash}"
                BorderBrush="{StaticResource DangerSoft}" BorderThickness="0,0,0,1"
                IsVisible="{Binding Vault.HasHostKeyMismatch}">
          <StackPanel Spacing="6">
            <TextBlock Text="The host key changed and the connection was refused."
                       Foreground="{StaticResource Danger}" FontWeight="SemiBold" />
            <SelectableTextBlock Text="{Binding Vault.HostKeyMismatch}"
                                 Foreground="{StaticResource Danger}" TextWrapping="Wrap" />
            <TextBlock Text="If the server was legitimately rebuilt, edit the host and choose &quot;Forget host key&quot; first. There is deliberately no way to continue from here."
                       Foreground="{StaticResource WarnText}" TextWrapping="Wrap" />
          </StackPanel>
        </Border>

        <!--
          The conflict log. The merge is only allowed to pick a winner because the value it overrode is kept
          and shown; without this panel it would be last-writer-wins with a longer explanation.

          Bounded and scrollable, which it was not while it lived in the window. It sits on an Auto row above
          a star row, and an ItemsControl with no ceiling grows without limit — so a pass that merged twenty
          items pushed everything below it off the bottom of a screen nobody could scroll. It went unnoticed
          for as long as it did because no test could lay this markup out; that is the other half of why this
          file exists.
        -->
        <Border Padding="12,10" Background="{StaticResource Panel}"
                BorderBrush="{StaticResource Border}" BorderThickness="0,0,0,1"
                IsVisible="{Binding Vault.HasConflicts}">
          <StackPanel Spacing="6">
            <TextBlock Text="Some changes could not be merged automatically."
                       Foreground="{StaticResource Info}" FontWeight="SemiBold" />
            <ScrollViewer MaxHeight="180" HorizontalScrollBarVisibility="Disabled">
              <ItemsControl ItemsSource="{Binding Vault.Conflicts}">
                <ItemsControl.ItemTemplate>
                  <DataTemplate x:DataType="vm:ConflictRowViewModel">
                    <Border Margin="0,4" Padding="8" Background="{StaticResource Raised}"
                            CornerRadius="4">
                      <StackPanel Spacing="4">
                        <TextBlock Text="{Binding Summary}" Foreground="{StaticResource Text}"
                                   TextWrapping="Wrap" />
                        <SelectableTextBlock Classes="mono" Text="{Binding Detail}" FontSize="11"
                                             Foreground="{StaticResource TextDim}"
                                             IsVisible="{Binding HasDetail}" />
                      </StackPanel>
                    </Border>
                  </DataTemplate>
                </ItemsControl.ItemTemplate>
              </ItemsControl>
            </ScrollViewer>
            <Button Classes="ghost" Content="DISMISS ALL" HorizontalAlignment="Left"
                    Command="{Binding Vault.AcknowledgeAllConflictsCommand}" />
          </StackPanel>
        </Border>

      </StackPanel>

      <!--
        The overview proper: what is known about the host the list has selected.

        Every fact here is one the sidebar already computes, and that is deliberate. This column was a
        terminal until this screen stopped hosting one, and filling it with something that needed new state
        would be inventing a feature to fill a rectangle. What it is for is the question the screen now has
        to answer — "which machine is this, and how will it let me in" — before the answer scrolls past in a
        list of forty.
      -->
      <ScrollViewer Grid.Row="2" HorizontalScrollBarVisibility="Disabled">
        <Panel Margin="24">

          <StackPanel Spacing="10" HorizontalAlignment="Left" VerticalAlignment="Top"
                      IsVisible="{Binding Vault.SelectedHost, Converter={x:Static ObjectConverters.IsNotNull}}">
            <StackPanel Orientation="Horizontal" Spacing="8">
              <TextBlock Classes="heading" Text="{Binding Vault.SelectedHost.Label}"
                         VerticalAlignment="Center" />
              <Border Classes="chip" VerticalAlignment="Center"
                      IsVisible="{Binding Vault.SelectedHost.IsConnected}">
                <TextBlock Text="CONNECTED" />
              </Border>
            </StackPanel>

            <SelectableTextBlock Classes="mono" Text="{Binding Vault.SelectedHost.Address}"
                                 Foreground="{StaticResource TextDim}" />

            <TextBlock Classes="hint" Text="{Binding Vault.SelectedHost.Authentication}" />

            <TextBlock Classes="hint" FontSize="11" MaxWidth="440" TextWrapping="Wrap"
                       Text="Press CONNECT, or double-click the host in the list. The terminal opens in the strip above and stays there while you look at anything else." />
          </StackPanel>

          <TextBlock Classes="hint" HorizontalAlignment="Left" VerticalAlignment="Top"
                     MaxWidth="440" TextWrapping="Wrap"
                     Text="Choose a host on the left to see what it is and how it authenticates. Ctrl+K searches them by name."
                     IsVisible="{Binding Vault.SelectedHost, Converter={x:Static ObjectConverters.IsNull}}" />

        </Panel>
      </ScrollViewer>

      <!--
        Groups: making them, renaming them, and taking them away.

        Here rather than on the Keychain screen, because a group is not a secret — it is how this screen's
        list is arranged, and the arranging belongs beside the thing arranged. Filing a host into one is done
        in the host's own editor, on the left, for the same reason its key and its password are.

        One text box for both adding and renaming. A group has exactly one field, so a separate rename form
        would be this box with a different heading; GroupSaveLabel is what says which of the two is about to
        happen.
      -->
      <Border Grid.Row="3" Padding="12,10" Background="{StaticResource Panel}"
              BorderBrush="{StaticResource BorderSubtle}" BorderThickness="0,1,0,0">
        <StackPanel Spacing="8">

          <StackPanel Orientation="Horizontal" Spacing="8">
            <TextBlock Classes="label" Text="GROUPS" Foreground="{StaticResource TextDim}"
                       VerticalAlignment="Center" />
            <TextBlock Classes="hint" FontSize="10.5" VerticalAlignment="Center" TextWrapping="Wrap"
                       Text="Headings for the list on the left. Which group a host is in is part of the host, and stays encrypted." />
          </StackPanel>

          <!--
            Horizontal, because a group is a name and a count: a vertical list of one-line rows would take a
            third of this column to say what a row of chips says in one line.
          -->
          <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled"
                        IsVisible="{Binding Vault.HasGroups}">
            <ListBox ItemsSource="{Binding Vault.Groups}" SelectedItem="{Binding Vault.SelectedGroup}"
                     Background="Transparent" MaxHeight="72">
              <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                  <StackPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
              </ListBox.ItemsPanel>
              <ListBox.ItemTemplate>
                <DataTemplate x:DataType="vm:HostGroupRowViewModel">
                  <StackPanel Margin="2,4" Spacing="1">
                    <StackPanel Orientation="Horizontal" Spacing="6">
                      <TextBlock Classes="mono" Text="{Binding Label}" Foreground="{StaticResource Text}"
                                 FontSize="11.5" />
                      <Border Classes="chip warn" Padding="4,0"
                              IsVisible="{Binding Badge, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
                        <TextBlock Text="{Binding Badge}" FontSize="8.5" />
                      </Border>
                    </StackPanel>
                    <TextBlock Classes="mono" Text="{Binding Description}" FontSize="9.5"
                               Foreground="{StaticResource TextFaint}" />
                  </StackPanel>
                </DataTemplate>
              </ListBox.ItemTemplate>
            </ListBox>
          </ScrollViewer>

          <StackPanel Orientation="Horizontal" Spacing="6" IsVisible="{Binding Vault.ShowsGroupActions}">
            <TextBox Text="{Binding Vault.GroupEditorLabel}" PlaceholderText="group name" Width="180"
                     FontSize="11" MinHeight="26" Padding="8,3" />
            <Button Classes="ghost" Content="{Binding Vault.GroupSaveLabel}"
                    Command="{Binding Vault.SaveGroupCommand}" />
            <Button Classes="ghost" Content="RENAME SELECTED" Command="{Binding Vault.EditGroupCommand}" />
            <Button Classes="ghost" Content="DELETE" Command="{Binding Vault.DeleteGroupCommand}" />
          </StackPanel>

          <!--
            Swapped for the buttons rather than stacked under them, as the sidebar's own question is, so
            DELETE cannot be pressed again while its answer is on screen. It asks its own question only: the
            two panels share one pending deletion, and the sidebar checks the same way.
          -->
          <Border Padding="8" Background="{StaticResource DangerWash}" CornerRadius="4"
                  IsVisible="{Binding Vault.IsConfirmingGroupDeletion}">
            <views:ConfirmDeleteCard DataContext="{Binding Vault}" />
          </Border>

        </StackPanel>
      </Border>

    </Grid>
  </Grid>

</UserControl>
