// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

library fuchsia.ui.text;

/// Lists the Positions for selection and other related ranges, at a particular
/// revision number. Any time the revision number is incremented, all these Positions
/// become invalid, and a new TextFieldState is sent through OnUpdate.
table TextFieldState {
    /// (required) The start and end of the entire text field.
    1: Range document;

    /// (required) The currently selected range of text.
    2: Selection selection;

    /// The range that indicates the text that is being composed, or currently
    /// receiving suggestions from the keyboard. It should be displayed in some
    /// distinct way, such as underlined.
    3: Range composition;

    /// Some keyboards, notably Japanese, give the user buttons to highlight just a
    /// subset of the composition string for suggestions. It must be equal to or a subset
    /// of the composition range. If the composition range changes, the TextField may
    /// discard this and require the keyboard to create a new one.
    4: Range composition_highlight;

    /// A dead key is a key combination you press before another key to add diacritical
    /// marks, accents, or other changes to the second key. After the first key, a
    /// highlighted character indicates that the next character will be different. This
    /// range is that highlighted character. If the selection moves away from this
    /// highlight range, or if the contents of the highlight range change, the TextField
    /// may discard this and require the keyboard to create a new one.
    5: Range dead_key_highlight;

    /// (required) This number is increased any time content in the text field is changed,
    /// if the selection is changed, or if anything else about the state is changed.
    6: uint64 revision;
};

/// Indicates errors that can occur with various TextField methods. Until FIDL supports
/// result return types, if Error has any value except OK, the client must ignore
/// all other return data from that method.
enum Error {
    // Once FIDL supports Result return types, this option can be removed.
    OK = 0;

    /// Indicates the revision number passed to the method is no longer valid.
    BAD_REVISION = 1;

    /// Indicates an edit would be valid, but custom text field code does not allow that change
    /// to be made, like inserting number into a text field.
    INVALID_EDIT = 2;

    /// Bad request entirely, like an unknown position that doesn't match the edits revision.
    /// Indicates a bug with client code.
    BAD_REQUEST = 3;

    /// For a contents() request, indicates there is no text between the two position that is known.
    /// (If only a substring is known, it should be returned, with the `start` Position set
    /// appropriately). For a distance() request, indicates the number of characters between the
    /// two position is unknowably large.
    UNKNOWABLE = 4;
};

/// Represents a text field or other kind of editing interface that wants to receive text input
/// from the operating system. This interface is also what is passed to a keyboard to allow it
/// to read state and make changes to text fields.
///
/// All editing methods must happen within an edit transaction. The edits aren't
/// applied until CommitEdit is called. **This isn't a lock!** The TextField
/// can still apply edits on its side, which would increase the current revision
/// number. When CommitEdit is called, the edits are only run if the revision
/// number passed to BeginEdit is still valid. TextField implementations can
/// assume that there will only be one client at a time; they don't need to
/// keep track of a separate transaction list for each client.
protocol TextField {
    /// Any time the revision number increments, this event fires, with the latest version of
    /// the state. It also fires when a new client connects to the service, so it can get an
    /// initial state without waiting for an edit.
    -> OnUpdate(TextFieldState state);

    // READ METHODS

    /// Returns a new position that is `offset` unicode code points away from `old_position`
    PositionOffset(Position old_position, int64 offset, uint64 revision) -> (Position new_position, Error error);

    /// Returns number of unicode code points between two positions. If the position range.start is after
    /// range.end, then the range is considered `inverted` and distance will be negative.
    /// For all positions A and B, PositionOffset(A, Distance(A, B)) == B
    Distance(Range range, uint64 revision) -> (int64 distance, Error error);

    /// Returns string of unicode code points between two positions
    Contents(Range range, uint64 revision) -> (string contents, Position start, Error error);

    // TRANSACTION METHODS

    /// Starts a transaction. If it's called a second time with no CommitEdit()
    /// call, the changes from the first uncommitted transaction are discarded as
    /// though AbortEdit() was called.
    BeginEdit(uint64 revision);

    /// If the transaction's revision number (from BeginEdit) is still current,
    /// runs all edit commands queued in this transaction. If not, returns
    /// `BAD_REVISION`.
    CommitEdit() -> (Error error);

    /// Discards the current transaction.
    AbortEdit();

    // EDITING METHODS — used within a transaction

    /// Replaces text in the range with new_text. It's the client's
    /// responsibility to make sure new_text isn't too long for a FIDL message;
    /// if it is, the client should break up the string into separate replace
    /// calls.
    Replace(Range range, string new_text);

    /// Sets the selection range.
    SetSelection(Selection selection);

    /// Sets the composition range and the composition highlight range. For more info,
    /// see TextState's comments.
    SetComposition(Range composition_range, Range? highlight_range);

    /// Clears both the composition range, and the composition highlight range.
    ClearComposition();

    /// Sets the dead key highlight range. For more info, see TextState's comments.
    SetDeadKeyHighlight(Range range);

    /// Clears the dead key highlight range.
    ClearDeadKeyHighlight();
};
