// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
// The header provides a set of helper utils for protobuf related operations.
// The APIs may not be finalized yet.

#pragma once

#include <cstddef>
#include <string_view>

#include "pw_assert/check.h"
#include "pw_protobuf/internal/proto_integer_base.h"
#include "pw_protobuf/stream_decoder.h"
#include "pw_status/status.h"
#include "pw_status/try.h"
#include "pw_stream/interval_reader.h"
#include "pw_stream/stream.h"

namespace pw::protobuf {

// The following defines classes that represent various parsed proto integer
// types or an error code to indicate parsing failure.
//
// For normal uses, the class should be created from `class Message`. See
// comment for `class Message` for usage.

class Uint32 : public internal::ProtoIntegerBase<uint32_t> {
 public:
  using ProtoIntegerBase<uint32_t>::ProtoIntegerBase;
};

class Int32 : public internal::ProtoIntegerBase<int32_t> {
 public:
  using ProtoIntegerBase<int32_t>::ProtoIntegerBase;
};

class Sint32 : public internal::ProtoIntegerBase<int32_t> {
 public:
  using ProtoIntegerBase<int32_t>::ProtoIntegerBase;
};

class Fixed32 : public internal::ProtoIntegerBase<uint32_t> {
 public:
  using ProtoIntegerBase<uint32_t>::ProtoIntegerBase;
};

class Sfixed32 : public internal::ProtoIntegerBase<int32_t> {
 public:
  using ProtoIntegerBase<int32_t>::ProtoIntegerBase;
};

class Uint64 : public internal::ProtoIntegerBase<uint64_t> {
 public:
  using ProtoIntegerBase<uint64_t>::ProtoIntegerBase;
};

class Int64 : public internal::ProtoIntegerBase<int64_t> {
 public:
  using ProtoIntegerBase<int64_t>::ProtoIntegerBase;
};

class Sint64 : public internal::ProtoIntegerBase<int64_t> {
 public:
  using ProtoIntegerBase<int64_t>::ProtoIntegerBase;
};

class Fixed64 : public internal::ProtoIntegerBase<uint64_t> {
 public:
  using ProtoIntegerBase<uint64_t>::ProtoIntegerBase;
};

class Sfixed64 : public internal::ProtoIntegerBase<int64_t> {
 public:
  using ProtoIntegerBase<int64_t>::ProtoIntegerBase;
};

class Float : public internal::ProtoIntegerBase<float> {
 public:
  using ProtoIntegerBase<float>::ProtoIntegerBase;
};

class Double : public internal::ProtoIntegerBase<double> {
 public:
  using ProtoIntegerBase<double>::ProtoIntegerBase;
};

class Bool : public internal::ProtoIntegerBase<bool> {
 public:
  using ProtoIntegerBase<bool>::ProtoIntegerBase;
};

// An object that represents a parsed `bytes` field or an error code. The
// bytes are available via an stream::IntervalReader by GetBytesReader().
//
// For normal uses, the class should be created from `class Message`. See
// comment for `class Message` for usage.
class Bytes {
 public:
  Bytes() = default;
  Bytes(Status status) : reader_(status) {}
  Bytes(stream::IntervalReader reader) : reader_(reader) {}
  stream::IntervalReader GetBytesReader() { return reader_; }

  // TODO(pwbug/363): Migrate this to Result<> once we have StatusOr like
  // support.
  bool ok() { return reader_.ok(); }
  Status status() { return reader_.status(); }

  // Check whether the bytes value equals the given `bytes`.
  // TODO(pwbug/456): Should this return `bool`? In the case of error, is it ok
  // to just return false?
  Result<bool> Equal(ConstByteSpan bytes);

 private:
  stream::IntervalReader reader_;
};

// An object that represents a parsed `string` field or an error code. The
// string value is available via an stream::IntervalReader by
// GetBytesReader().
//
// For normal uses, the class should be created from `class Message`. See
// comment for `class Message` for usage.
class String : public Bytes {
 public:
  using Bytes::Bytes;

  // Check whether the string value equals the given `str`
  Result<bool> Equal(std::string_view str);
};

// Forward declaration of parser classes.
template <typename FieldType>
class RepeatedFieldParser;
template <typename FieldType>
class StringMapEntryParser;
template <typename FieldType>
class StringMapParser;
class Message;

using RepeatedBytes = RepeatedFieldParser<Bytes>;
using RepeatedStrings = RepeatedFieldParser<String>;
using RepeatedMessages = RepeatedFieldParser<Message>;
using StringToBytesMapEntry = StringMapEntryParser<Bytes>;
using StringToStringMapEntry = StringMapEntryParser<String>;
using StringToMessageMapEntry = StringMapEntryParser<Message>;
using StringToBytesMap = StringMapParser<Bytes>;
using StringToStringMap = StringMapParser<String>;
using StringToMessageMap = StringMapParser<Message>;

// Message - A helper class for parsing a proto message.
//
// Examples:
//
// message Nested {
//   string nested_str = 1;
//   bytes nested_bytes = 2;
// }
//
// message {
//   string str = 1;
//   bytes bytes = 2;
//   uint32 integer = 3
//   repeated string rep_str = 4;
//   map<string, bytes> str_to_bytes = 5;
//   Nested nested = 6;
// }
//
//   // Given a seekable `reader` that reads the top-level proto message, and
//   // a <size> that gives the size of the proto message:
//   Message message(reader, <size>);
//
//   // Prase simple basic value fields
//   String str = message.AsString(1); // string
//   Bytes bytes = message.AsBytes(2); // bytes
//   Uint32 integer = messasge_parser.AsUint32(3); // uint32 integer
//
//   // Parse repeated field `repeated string rep_str = 4;`
//   RepeatedStrings rep_str = message.AsRepeatedString(4);
//   // Iterate through the entries. If proto is malformed when
//   // iterating, the next element (`str` in this case) will be invalid
//   // and loop will end in the iteration after.
//   for (String str : rep_str) {
//     // Check status
//     if (!str.ok()) {
//       // In the case of error, loop will end in the next iteration if
//       // continues. This is the chance for code to catch the error.
//       ...
//     }
//     ...
//   }
//
//   // Parse map field `map<string, bytes> str_to_bytes = 5;`
//   StringToBytesMap str_to_bytes = message.AsStringToBytesMap(5);
//
//   // Access the entry by a given key value
//   Bytes bytes_for_key = str_to_bytes["key"];
//
//   // Or iterate through map entries
//   for (StringToBytesMapEntry entry : str_to_bytes) {
//     if (!entry.ok()) {
//       // In the case of error, loop will end in the next iteration if
//       // continues. This is the chance for code to catch the error.
//       ...
//     }
//     String key = entry.Key();
//     Bytes value = entry.Value();
//     ...
//   }
//
//   // Parse nested message `Nested nested = 6;`
//   Message nested = message.AsMessage(6).
//   String nested_str = nested.AsString(1);
//   Bytes nested_bytes = nested.AsBytes(2);
//
//   // The `AsXXX()` methods above internally traverse all the fields to find
//   // the one with the give field number. This can be expensive if called
//   // multiple times. Therefore, whenever possible, it is recommended to use
//   // the following iteration to iterate and process each field directly.
//   for (Message::Field field : message) {
//     if (!field.ok()) {
//       // In the case of error, loop will end in the next iteration if
//       // continues. This is the chance for code to catch the error.
//       ...
//     }
//     if (field.field_number() == 1) {
//       String str = field.As<String>();
//       ...
//     } else if (field.field_number() == 2) {
//       Bytes bytes = field.As<Bytes>();
//       ...
//     } else if (field.field_number() == 6) {
//       Message nested = field.As<Message>();
//       ...
//     }
//   }
//
// All parser objects created above internally hold the same reference
// to `reader`. Therefore it needs to maintain valid lifespan throughout the
// operations. The parser objects can work independently and without blocking
// each other. All method calls and for-iterations above are re-enterable.
class Message {
 public:
  class Field {
   public:
    uint32_t field_number() { return field_number_; }
    const stream::IntervalReader& field_reader() { return field_reader_; }
    bool ok() { return field_reader_.ok(); }
    Status status() { return field_reader_.status(); }

    // Create a helper parser type of `FieldType` for the field.
    // The default implementation below assumes the field is a length-delimited
    // field. Other cases such as primitive integer uint32 will be handled by
    // template specialization.
    template <typename FieldType>
    FieldType As() {
      if (!field_reader_.ok()) {
        return FieldType(field_reader_.status());
      }

      StreamDecoder decoder(field_reader_.Reset());
      PW_TRY(decoder.Next());
      Result<StreamDecoder::Bounds> payload_bounds =
          decoder.GetLengthDelimitedPayloadBounds();
      PW_TRY(payload_bounds.status());
      // The bounds is relative to the given stream::IntervalReader. Convert
      // it to the interval relative to the source_reader.
      return FieldType(stream::IntervalReader(
          field_reader_.source_reader(),
          payload_bounds.value().low + field_reader_.start(),
          payload_bounds.value().high + field_reader_.start()));
    }

   private:
    Field() = default;
    Field(Status status) : field_reader_(status), field_number_(0) {}
    Field(stream::IntervalReader reader, uint32_t field_number)
        : field_reader_(reader), field_number_(field_number) {}

    stream::IntervalReader field_reader_;
    uint32_t field_number_;

    friend class Message;
  };

  class iterator {
   public:
    iterator& operator++();

    iterator operator++(int) {
      iterator iter = *this;
      this->operator++();
      return iter;
    }

    bool ok() { return status_.ok(); }
    Status status() { return status_; }
    Field operator*() { return current_; }
    Field* operator->() { return &current_; }
    bool operator!=(const iterator& other) const { return !(*this == other); }

    bool operator==(const iterator& other) const {
      return eof_ == other.eof_ && reader_ == other.reader_;
    }

   private:
    stream::IntervalReader reader_;
    bool eof_ = false;
    Field current_;
    Status status_ = OkStatus();

    iterator(stream::IntervalReader reader) : reader_(reader) {
      this->operator++();
    }

    friend class Message;
  };

  Message() = default;
  Message(Status status) : reader_(status) {}
  Message(stream::IntervalReader reader) : reader_(reader) {}
  Message(stream::SeekableReader& proto_source, size_t size)
      : reader_(proto_source, 0, size) {}

  // Parse a sub-field in the message given by `field_number` as bytes.
  Bytes AsBytes(uint32_t field_number) { return As<Bytes>(field_number); }

  // Parse a sub-field in the message given by `field_number` as string.
  String AsString(uint32_t field_number) { return As<String>(field_number); }

  // Parse a sub-field in the message given by `field_number` as one of the
  // proto integer type.
  Int32 AsInt32(uint32_t field_number) { return As<Int32>(field_number); }
  Sint32 AsSint32(uint32_t field_number) { return As<Sint32>(field_number); }
  Uint32 AsUint32(uint32_t field_number) { return As<Uint32>(field_number); }
  Fixed32 AsFixed32(uint32_t field_number) { return As<Fixed32>(field_number); }
  Int64 AsInt64(uint32_t field_number) { return As<Int64>(field_number); }
  Sint64 AsSint64(uint32_t field_number) { return As<Sint64>(field_number); }
  Uint64 AsUint64(uint32_t field_number) { return As<Uint64>(field_number); }
  Fixed64 AsFixed64(uint32_t field_number) { return As<Fixed64>(field_number); }

  Sfixed32 AsSfixed32(uint32_t field_number) {
    return As<Sfixed32>(field_number);
  }

  Sfixed64 AsSfixed64(uint32_t field_number) {
    return As<Sfixed64>(field_number);
  }

  Float AsFloat(uint32_t field_number) { return As<Float>(field_number); }
  Double AsDouble(uint32_t field_number) { return As<Double>(field_number); }

  Bool AsBool(uint32_t field_number) { return As<Bool>(field_number); }

  // Parse a sub-field in the message given by `field_number` as another
  // message.
  Message AsMessage(uint32_t field_number) { return As<Message>(field_number); }

  // Parse a sub-field in the message given by `field_number` as `repeated
  // string`.
  RepeatedBytes AsRepeatedBytes(uint32_t field_number);

  // Parse a sub-field in the message given by `field_number` as `repeated
  // string`.
  RepeatedStrings AsRepeatedStrings(uint32_t field_number);

  // Parse a sub-field in the message given by `field_number` as `repeated
  // message`.
  RepeatedMessages AsRepeatedMessages(uint32_t field_number);

  // Parse a sub-field in the message given by `field_number` as `map<string,
  // message>`.
  StringToMessageMap AsStringToMessageMap(uint32_t field_number);

  // Parse a sub-field in the message given by `field_number` as
  // `map<string, bytes>`.
  StringToBytesMap AsStringToBytesMap(uint32_t field_number);

  // Parse a sub-field in the message given by `field_number` as
  // `map<string, string>`.
  StringToStringMap AsStringToStringMap(uint32_t field_number);

  // Convert the message to a Bytes that represents the raw bytes of this
  // message. This can be used to obatained the serialized wire-format of the
  // message.
  Bytes ToBytes() { return Bytes(reader_.Reset()); }

  // TODO(pwbug/363): Migrate this to Result<> once we have StatusOr like
  // support.
  bool ok() { return reader_.ok(); }
  Status status() { return reader_.status(); }

  iterator begin();
  iterator end();

  // Parse a field given by `field_number` as the target parser type
  // `FieldType`.
  //
  // Note: This method assumes that the message has only 1 field with the given
  // <field_number>. It returns the first matching it find. It does not perform
  // value overridding or string concatenation for multiple fields with the same
  // <field_number>.
  //
  // Since the method needs to traverse all fields, it can be inefficient if
  // called multiple times exepcially on slow reader.
  template <typename FieldType>
  FieldType As(uint32_t field_number) {
    for (Field field : *this) {
      if (field.field_number() == field_number) {
        return field.As<FieldType>();
      }
    }

    return FieldType(Status::NotFound());
  }

  template <typename FieldType>
  RepeatedFieldParser<FieldType> AsRepeated(uint32_t field_number) {
    return RepeatedFieldParser<FieldType>(*this, field_number);
  }

  template <typename FieldParser>
  StringMapParser<FieldParser> AsStringMap(uint32_t field_number) {
    return StringMapParser<FieldParser>(*this, field_number);
  }

 private:
  stream::IntervalReader reader_;

  // Consume the current field. If the field has already been processed, i.e.
  // by calling one of the Read..() method, nothing is done. After calling this
  // method, the reader will be pointing either to the start of the next
  // field (i.e. the starting offset of the field key), or the end of the
  // stream. The method is for use by Message for computing field interval.
  static Status ConsumeCurrentField(StreamDecoder& decoder) {
    return decoder.field_consumed_ ? OkStatus() : decoder.SkipField();
  }
};

// The following are template specialization for proto integer types.
template <>
Uint32 Message::Field::As<Uint32>();

template <>
Int32 Message::Field::As<Int32>();

template <>
Sint32 Message::Field::As<Sint32>();

template <>
Fixed32 Message::Field::As<Fixed32>();

template <>
Sfixed32 Message::Field::As<Sfixed32>();

template <>
Uint64 Message::Field::As<Uint64>();

template <>
Int64 Message::Field::As<Int64>();

template <>
Sint64 Message::Field::As<Sint64>();

template <>
Fixed64 Message::Field::As<Fixed64>();

template <>
Sfixed64 Message::Field::As<Sfixed64>();

template <>
Float Message::Field::As<Float>();

template <>
Double Message::Field::As<Double>();

template <>
Bool Message::Field::As<Bool>();

// A helper for parsing `repeated` field. It implements an iterator interface
// that only iterates through the fields of a given `field_number`.
//
// For normal uses, the class should be created from `class Message`. See
// comment for `class Message` for usage.
template <typename FieldType>
class RepeatedFieldParser {
 public:
  class iterator {
   public:
    // Precondition: iter_ is not pointing to the end.
    iterator& operator++() {
      iter_++;
      MoveToNext();
      return *this;
    }

    iterator operator++(int) {
      iterator iter = *this;
      this->operator++();
      return iter;
    }

    bool ok() { return iter_.ok(); }
    Status status() { return iter_.status(); }
    FieldType operator*() { return current_; }
    FieldType* operator->() { return &current_; }
    bool operator!=(const iterator& other) const { return !(*this == other); }
    bool operator==(const iterator& other) const {
      return &host_ == &other.host_ && iter_ == other.iter_;
    }

   private:
    RepeatedFieldParser& host_;
    Message::iterator iter_;
    FieldType current_ = FieldType(Status::Unavailable());

    iterator(RepeatedFieldParser& host, Message::iterator init_iter)
        : host_(host), iter_(init_iter), current_(Status::Unavailable()) {
      // Move to the first element of the target field number.
      MoveToNext();
    }

    void MoveToNext() {
      // Move the iterator to the next element with the target field number
      for (; iter_ != host_.message_.end(); ++iter_) {
        if (!iter_.ok() || iter_->field_number() == host_.field_number_) {
          current_ = iter_->As<FieldType>();
          break;
        }
      }
    }

    friend class RepeatedFieldParser;
  };

  // `message` -- The containing message.
  // `field_number` -- The field number of the repeated field.
  RepeatedFieldParser(Message& message, uint32_t field_number)
      : message_(message), field_number_(field_number) {}

  RepeatedFieldParser(Status status) : message_(status) {}

  // TODO(pwbug/363): Migrate this to Result<> once we have StatusOr like
  // support.
  bool ok() { return message_.ok(); }
  Status status() { return message_.status(); }

  iterator begin() { return iterator(*this, message_.begin()); }
  iterator end() { return iterator(*this, message_.end()); }

 private:
  Message message_;
  uint32_t field_number_ = 0;
};

// A helper for pasring the entry type of map<string, <value>>.
// An entry for a proto map is essentially a message of a key(k=1) and
// value(k=2) field, i.e.:
//
// message Entry {
//   string key = 1;
//   bytes value = 2;
// }
//
// For normal uses, the class should be created from `class Message`. See
// comment for `class Message` for usage.
template <typename ValueParser>
class StringMapEntryParser {
 public:
  bool ok() { return entry_.ok(); }
  Status status() { return entry_.status(); }
  StringMapEntryParser(Status status) : entry_(status) {}
  StringMapEntryParser(stream::IntervalReader reader) : entry_(reader) {}
  String Key() { return entry_.AsString(kMapKeyFieldNumber); }
  ValueParser Value() { return entry_.As<ValueParser>(kMapValueFieldNumber); }

 private:
  static constexpr uint32_t kMapKeyFieldNumber = 1;
  static constexpr uint32_t kMapValueFieldNumber = 2;
  Message entry_;
};

// A helper class for parsing a string-keyed map field. i.e. map<string,
// <value>>. The template argument `ValueParser` indicates the type the value
// will be parsed as, i.e. String, Bytes, Uint32, Message etc.
//
// For normal uses, the class should be created from `class Message`. See
// comment for `class Message` for usage.
template <typename ValueParser>
class StringMapParser
    : public RepeatedFieldParser<StringMapEntryParser<ValueParser>> {
 public:
  using RepeatedFieldParser<
      StringMapEntryParser<ValueParser>>::RepeatedFieldParser;

  // Operator overload for value access of a given key.
  ValueParser operator[](std::string_view target) {
    // Iterate over all entries and find the one whose key matches `target`
    for (StringMapEntryParser<ValueParser> entry : *this) {
      String key = entry.Key();
      PW_TRY(key.status());

      // Compare key value with the given string
      Result<bool> cmp_res = key.Equal(target);
      PW_TRY(cmp_res.status());
      if (cmp_res.value()) {
        return entry.Value();
      }
    }

    return ValueParser(Status::NotFound());
  }
};

}  // namespace pw::protobuf
