// 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
//   for (String str : rep_str) {
//     ...
//   }
//
//   // 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) {
//     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.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_; }

    // 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() {
      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(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;
    }

    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_;

    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;
    }

    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_;
    bool eof_ = false;
    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_->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:
  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
