/* @flow strict-local */
import React, { PureComponent } from 'react';

import * as api from '../api';
import type { Auth, Dispatch, Message } from '../types';
import { Screen } from '../common';
import SearchMessagesCard from './SearchMessagesCard';
import styles from '../styles';
import { SEARCH_NARROW } from '../utils/narrow';
import { LAST_MESSAGE_ANCHOR } from '../constants';
import { connect } from '../react-redux';
import { getAuth } from '../account/accountsSelectors';

type Props = {|
  auth: Auth,
  dispatch: Dispatch,
|};

type State = {|
  messages: Message[] | null,
  isFetching: boolean,
|};

class SearchMessagesScreen extends PureComponent<Props, State> {
  state = {
    messages: null,
    isFetching: false,
  };

  performQuery = async (query: string) => {
    const { auth } = this.props;

    this.setState({ isFetching: true });

    const { messages } = await api.getMessages(
      auth,
      SEARCH_NARROW(query),
      LAST_MESSAGE_ANCHOR,
      20,
      0,
      false,
    );

    this.setState({ messages, isFetching: false });
  };

  handleQueryChange = (query: string) => {
    if (query !== '') {
      this.performQuery(query);
    } else {
      this.setState({ messages: null, isFetching: false });
    }
  };

  render() {
    const { messages, isFetching } = this.state;

    return (
      <Screen search autoFocus searchBarOnChange={this.handleQueryChange} style={styles.flexed}>
        <SearchMessagesCard messages={messages} isFetching={isFetching} />
      </Screen>
    );
  }
}

export default connect(state => ({
  auth: getAuth(state),
}))(SearchMessagesScreen);

@@ -532,28 +532,326 @@
 ch,%0A
-%7C%7D;%0A%0Atype State = %7B%7C
+  // Warning: do not add new props without considering their effect on the%0A  // behavior of this component's non-React internal state. See comment below.%0A%7C%7D;%0A%0Atype State = %7B%7C%0A  /** The list of messages returned for the latest query, or %60null%60 if there is%0A   *  effectively no %22latest query%22 to have results from.%0A   */
 %0A  m
@@ -1031,16 +1031,158 @@
 ,%0A  %7D;%0A%0A
+  /** PRIVATE%0A   *  Performs a network request associated with a query. Does not%0A   *  update or access internal state (except %60auth%60).%0A   */%0A
   perfor
@@ -1187,16 +1187,19 @@
 ormQuery
+Raw
  = async
@@ -1206,32 +1206,52 @@
  (query: string)
+: Promise%3CMessage%5B%5D%3E
  =%3E %7B%0A    const 
@@ -1277,51 +1277,8 @@
 ps;%0A
-%0A    this.setState(%7B isFetching: true %7D);%0A%0A
     
@@ -1427,17 +1427,1004 @@
 %0A    );%0A
-%0A
+    return messages;%0A  %7D;%0A%0A  // Non-React state. See comment following.%0A  lastIdSent: number = 1000;%0A  lastIdReceived: number = 1000;%0A%0A  // This component is less pure than it should be. The correct behavior here is%0A  // probably that, when props change, all outstanding asynchronous requests%0A  // should be **synchronously** invalidated before the next render.%0A  //%0A  // As the only React prop this component has is %60auth%60, we ignore this for%0A  // now: any updates to %60auth%60 would involve this screen being torn down and%0A  // reconstructed anyway. However, addition of any new props which need to%0A  // invalidate outstanding requests on change will require more work.%0A%0A  handleQueryChange = (query: string) =%3E %7B%0A    if (query === '') %7B%0A      // The empty query can be resolved without a network call,%0A      // and should avoid throttling. (Ideally it should also cancel%0A      // pending throttled requests, but that's probably overkill.)%0A      this.lastIdReceived = ++this.lastIdSent;%0A  
     this
@@ -2435,32 +2435,38 @@
 State(%7B messages
+: null
 , isFetching: fa
@@ -2473,16 +2473,77 @@
 lse %7D);%0A
+      return;%0A    %7D%0A%0A    this.handleQueryChangeInner(query);%0A
   %7D;%0A%0A  
@@ -2551,34 +2551,45 @@
 andleQueryChange
- =
+Inner = async
  (query: string)
@@ -2602,33 +2602,106 @@
     
-if (query !== '') %7B%0A     
+const id = ++this.lastIdSent;%0A%0A    this.setState(%7B isFetching: true %7D);%0A    const messages = await
  thi
@@ -2714,16 +2714,19 @@
 ormQuery
+Raw
 (query);
@@ -2730,23 +2730,151 @@
 y);%0A
+%0A
     
-%7D else %7B%0A  
+if (this.lastIdReceived %3E id) %7B%0A      return;%0A    %7D%0A%0A    this.lastIdReceived = id;%0A%0A    // A query is concluded. Report the message-list.%0A
     
@@ -2889,38 +2889,32 @@
 State(%7B messages
-: null
 , isFetching: fa
@@ -2921,22 +2921,16 @@
 lse %7D);%0A
-    %7D%0A
   %7D;%0A%0A  

enforce ordering on network requests