// rational.h

// 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
//
//     http://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.
//
// Copyright 2005-2010 Google, Inc.
// Author: riley@google.com (Michael Riley)
//
// \file
// An Fst implementation and base interface for delayed unions,
// concatenations and closures.

#ifndef FST_LIB_RATIONAL_H__
#define FST_LIB_RATIONAL_H__

#include <algorithm>
#include <string>
#include <vector>
using std::vector;

#include <fst/mutable-fst.h>
#include <fst/replace.h>
#include <fst/test-properties.h>


namespace fst {

typedef CacheOptions RationalFstOptions;

// This specifies whether to add the empty string.
enum ClosureType { CLOSURE_STAR = 0,    // T* -> add the empty string
                   CLOSURE_PLUS = 1 };  // T+ -> don't add the empty string

template <class A> class RationalFst;
template <class A> void Union(RationalFst<A> *fst1, const Fst<A> &fst2);
template <class A> void Concat(RationalFst<A> *fst1, const Fst<A> &fst2);
template <class A> void Concat(const Fst<A> &fst1, RationalFst<A> *fst2);
template <class A> void Closure(RationalFst<A> *fst, ClosureType closure_type);


// Implementation class for delayed unions, concatenations and closures.
template<class A>
class RationalFstImpl : public FstImpl<A> {
 public:
  using FstImpl<A>::SetType;
  using FstImpl<A>::SetProperties;
  using FstImpl<A>::WriteHeader;
  using FstImpl<A>::SetInputSymbols;
  using FstImpl<A>::SetOutputSymbols;

  typedef A Arc;
  typedef typename A::Weight Weight;
  typedef typename A::StateId StateId;
  typedef typename A::Label Label;

  explicit RationalFstImpl(const RationalFstOptions &opts)
      : nonterminals_(0),
        replace_(0),
        replace_options_(opts, 0) {
    SetType("rational");
    fst_tuples_.push_back(pair<Label, const Fst<A>*>(0, 0));
  }

  RationalFstImpl(const RationalFstImpl<A> &impl)
      : rfst_(impl.rfst_),
        nonterminals_(impl.nonterminals_),

        replace_(impl.replace_ ? impl.replace_->Copy(true) : 0),
        replace_options_(impl.replace_options_) {
    SetType("rational");
    fst_tuples_.reserve(impl.fst_tuples_.size());
    for (size_t i = 0; i < impl.fst_tuples_.size(); ++i)
      fst_tuples_.push_back(make_pair(impl.fst_tuples_[i].first,
                                      impl.fst_tuples_[i].second
                                      ? impl.fst_tuples_[i].second->Copy(true)
                                      : 0));
  }

  virtual ~RationalFstImpl() {
    for (size_t i = 0; i < fst_tuples_.size(); ++i)
      if (fst_tuples_[i].second)
        delete fst_tuples_[i].second;
    if (replace_)
      delete replace_;
  }

  StateId Start() { return Replace()->Start(); }

  Weight Final(StateId s) { return Replace()->Final(s); }

  size_t NumArcs(StateId s) { return Replace()->NumArcs(s); }

  size_t NumInputEpsilons(StateId s) {
    return Replace()->NumInputEpsilons(s);
  }

  size_t NumOutputEpsilons(StateId s) {
    return Replace()->NumOutputEpsilons(s);
  }

  uint64 Properties() const { return Properties(kFstProperties); }

  // Set error if found; return FST impl properties.
  uint64 Properties(uint64 mask) const {
    if ((mask & kError) && Replace()->Properties(kError, false))
      SetProperties(kError, kError);
    return FstImpl<Arc>::Properties(mask);
  }

  // Implementation of UnionFst(fst1,fst2)
  void InitUnion(const Fst<A> &fst1, const Fst<A> &fst2) {
    if (replace_)
      delete replace_;
    uint64 props1 = fst1.Properties(kFstProperties, false);
    uint64 props2 = fst2.Properties(kFstProperties, false);
    SetInputSymbols(fst1.InputSymbols());
    SetOutputSymbols(fst1.OutputSymbols());
    rfst_.AddState();
    rfst_.AddState();
    rfst_.SetStart(0);
    rfst_.SetFinal(1, Weight::One());
    rfst_.SetInputSymbols(fst1.InputSymbols());
    rfst_.SetOutputSymbols(fst1.OutputSymbols());
    nonterminals_ = 2;
    rfst_.AddArc(0, A(0, -1, Weight::One(), 1));
    rfst_.AddArc(0, A(0, -2, Weight::One(), 1));
    fst_tuples_.push_back(make_pair(-1, fst1.Copy()));
    fst_tuples_.push_back(make_pair(-2, fst2.Copy()));
    SetProperties(UnionProperties(props1, props2, true), kCopyProperties);
  }

  // Implementation of ConcatFst(fst1,fst2)
  void InitConcat(const Fst<A> &fst1, const Fst<A> &fst2) {
    if (replace_)
      delete replace_;
    uint64 props1 = fst1.Properties(kFstProperties, false);
    uint64 props2 = fst2.Properties(kFstProperties, false);
    SetInputSymbols(fst1.InputSymbols());
    SetOutputSymbols(fst1.OutputSymbols());
    rfst_.AddState();
    rfst_.AddState();
    rfst_.AddState();
    rfst_.SetStart(0);
    rfst_.SetFinal(2, Weight::One());
    rfst_.SetInputSymbols(fst1.InputSymbols());
    rfst_.SetOutputSymbols(fst1.OutputSymbols());
    nonterminals_ = 2;
    rfst_.AddArc(0, A(0, -1, Weight::One(), 1));
    rfst_.AddArc(1, A(0, -2, Weight::One(), 2));
    fst_tuples_.push_back(make_pair(-1, fst1.Copy()));
    fst_tuples_.push_back(make_pair(-2, fst2.Copy()));
    SetProperties(ConcatProperties(props1, props2, true), kCopyProperties);
  }

  // Implementation of ClosureFst(fst, closure_type)
  void InitClosure(const Fst<A> &fst, ClosureType closure_type) {
    if (replace_)
      delete replace_;
    uint64 props = fst.Properties(kFstProperties, false);
    SetInputSymbols(fst.InputSymbols());
    SetOutputSymbols(fst.OutputSymbols());
    if (closure_type == CLOSURE_STAR) {
      rfst_.AddState();
      rfst_.SetStart(0);
      rfst_.SetFinal(0, Weight::One());
      rfst_.AddArc(0, A(0, -1, Weight::One(), 0));
    } else {
      rfst_.AddState();
      rfst_.AddState();
      rfst_.SetStart(0);
      rfst_.SetFinal(1, Weight::One());
      rfst_.AddArc(0, A(0, -1, Weight::One(), 1));
      rfst_.AddArc(1, A(0, 0, Weight::One(), 0));
    }
    rfst_.SetInputSymbols(fst.InputSymbols());
    rfst_.SetOutputSymbols(fst.OutputSymbols());
    fst_tuples_.push_back(make_pair(-1, fst.Copy()));
    nonterminals_ = 1;
    SetProperties(ClosureProperties(props, closure_type == CLOSURE_STAR, true),
                  kCopyProperties);
  }

  // Implementation of Union(Fst &, RationalFst *)
  void AddUnion(const Fst<A> &fst) {
    if (replace_)
      delete replace_;
    uint64 props1 = FstImpl<A>::Properties();
    uint64 props2 = fst.Properties(kFstProperties, false);
    VectorFst<A> afst;
    afst.AddState();
    afst.AddState();
    afst.SetStart(0);
    afst.SetFinal(1, Weight::One());
    ++nonterminals_;
    afst.AddArc(0, A(0, -nonterminals_, Weight::One(), 1));
    Union(&rfst_, afst);
    fst_tuples_.push_back(make_pair(-nonterminals_, fst.Copy()));
    SetProperties(UnionProperties(props1, props2, true), kCopyProperties);
  }

  // Implementation of Concat(Fst &, RationalFst *)
  void AddConcat(const Fst<A> &fst, bool append) {
    if (replace_)
      delete replace_;
    uint64 props1 = FstImpl<A>::Properties();
    uint64 props2 = fst.Properties(kFstProperties, false);
    VectorFst<A> afst;
    afst.AddState();
    afst.AddState();
    afst.SetStart(0);
    afst.SetFinal(1, Weight::One());
    ++nonterminals_;
    afst.AddArc(0, A(0, -nonterminals_, Weight::One(), 1));
    if (append)
      Concat(&rfst_, afst);
    else
      Concat(afst, &rfst_);
    fst_tuples_.push_back(make_pair(-nonterminals_, fst.Copy()));
    SetProperties(ConcatProperties(props1, props2, true), kCopyProperties);
  }

  // Implementation of Closure(RationalFst *, closure_type)
  void AddClosure(ClosureType closure_type) {
    if (replace_)
      delete replace_;
    uint64 props = FstImpl<A>::Properties();
    Closure(&rfst_, closure_type);
    SetProperties(ClosureProperties(props, closure_type == CLOSURE_STAR, true),
                  kCopyProperties);
  }

  // Returns the underlying ReplaceFst.
  ReplaceFst<A> *Replace() const {
    if (!replace_) {
      fst_tuples_[0].second = rfst_.Copy();
      replace_ = new ReplaceFst<A>(fst_tuples_, replace_options_);
    }
    return replace_;
  }

 private:
  VectorFst<A> rfst_;   // rational topology machine; uses neg. nonterminals
  Label nonterminals_;  // # of nonterminals used
  // Contains the nonterminals and their corresponding FSTs.
  mutable vector<pair<Label, const Fst<A>*> > fst_tuples_;
  mutable ReplaceFst<A> *replace_;        // Underlying ReplaceFst
  ReplaceFstOptions<A> replace_options_;  // Options for creating 'replace_'

  void operator=(const RationalFstImpl<A> &impl);    // disallow
};

// Parent class for the delayed rational operations - delayed union,
// concatenation, and closure.
//
// This class attaches interface to implementation and handles
// reference counting, delegating most methods to ImplToFst.
template <class A>
class RationalFst : public ImplToFst< RationalFstImpl<A> > {
 public:
  friend class StateIterator< RationalFst<A> >;
  friend class ArcIterator< RationalFst<A> >;
  friend void Union<>(RationalFst<A> *fst1, const Fst<A> &fst2);
  friend void Concat<>(RationalFst<A> *fst1, const Fst<A> &fst2);
  friend void Concat<>(const Fst<A> &fst1, RationalFst<A> *fst2);
  friend void Closure<>(RationalFst<A> *fst, ClosureType closure_type);

  typedef A Arc;
  typedef typename A::StateId StateId;
  typedef RationalFstImpl<A> Impl;

  virtual void InitStateIterator(StateIteratorData<A> *data) const {
    GetImpl()->Replace()->InitStateIterator(data);
  }

  virtual void InitArcIterator(StateId s, ArcIteratorData<A> *data) const {
    GetImpl()->Replace()->InitArcIterator(s, data);
  }

 protected:
  RationalFst()
      : ImplToFst<Impl>(new Impl(RationalFstOptions())) {}

  explicit RationalFst(const RationalFstOptions &opts)
      : ImplToFst<Impl>(new Impl(opts)) {}

  // See Fst<>::Copy() for doc.
  RationalFst(const RationalFst<A> &fst , bool safe = false)
      : ImplToFst<Impl>(fst, safe) {}

 private:
  // Makes visible to friends.
  Impl *GetImpl() const { return ImplToFst<Impl>::GetImpl(); }

  void operator=(const RationalFst<A> &fst);  // disallow
};


// Specialization for RationalFst.
template <class A>
class StateIterator< RationalFst<A> >
    : public StateIterator< ReplaceFst<A> > {
 public:
  explicit StateIterator(const RationalFst<A> &fst)
      : StateIterator< ReplaceFst<A> >(*(fst.GetImpl()->Replace())) {}
};


// Specialization for RationalFst.
template <class A>
class ArcIterator< RationalFst<A> >
    : public CacheArcIterator< ReplaceFst<A> > {
 public:
  typedef typename A::StateId StateId;

  ArcIterator(const RationalFst<A> &fst, StateId s)
      : ArcIterator< ReplaceFst<A> >(*(fst.GetImpl()->Replace()), s) {}
};

}  // namespace fst

#endif  // FST_LIB_RATIONAL_H__
