#ifndef OUTROS_FILMES_H
#define OUTROS_FILMES_H

#include <iosfwd>
#include <string>

#include "filme.H"

/** Representa filmes estrangeiros. 
    @invariant V. */
class FilmeEstrangeiro : public Filme {
public:
    /** Constrói novo filme estrangeiro com nome, realizador, duração,
	país e língua dados.
	@pre 0 <= duracao.
	@post nome() = nome e realizador() = realizador e duracao() =
	duracao e pais() = pais e lingua() = lingua. */
    FilmeEstrangeiro(std::string const& nome, std::string const& realizador,
                     int duracao, 
                     std::string const& pais, std::string const& lingua);

    /** Constrói novo filme estrangeiro com informação extraída do canal de
	entrada. 
	@pre entrada.
	@post *this tem informação extraída do canal de entrada. */
    explicit FilmeEstrangeiro(std::istream& entrada);
    
    /** Devolve o pais de origem do filme.
	@pre V.
	@post pais = país de origem do filme. */
    std::string const& pais() const;

    /** Devolve a língua do filme.
	@pre V.
	@post lingua = língua do filme. */
    std::string const& lingua() const;
    
    /** Mostra informação sobre o filme no canal dado num formato
	agradável à vista.
	@pre V.
	@post saida contém a informação sobre o filme. */
    void mostraEm(std::ostream&) const;

    /** Guarda informação sobre o filme no canal dado num formato
	apropriado a futuros carregamentos.
	@pre saida.
	@post saida contém a informação sobre o filme. */
    // void guardaEm(std::ostream&) const;

    /** Le informação sobre o filme do canal dado assumindo que este
	está ligado a um ser humano (e.g., leitura do teclado).
	@pre V.
	@post *this contém a informação sobre o filme lida do canal de
	entrada. */
    // void leDe(std::istream&);

    /** Carrega informação sobre o filme do canal dado assumindo que este
	está ligado no formato usado pela operação carrega().
	@pre entrada.
	@post *this contém a informação sobre o filme carregada do canal de
	entrada. */
    void carregaDe(std::istream&);
    
private:
    std::string lingua_;
    std::string pais_;

    /** Indica se a condição invariante da classe se verifica.
	@pre V.
	@post cumpreInvariante = V. */
    bool cumpreInvariante() const;
};

/** Representa filmes com edição do realizador. 
    @invariant V. */
class EdicaoDoRealizador : public Filme {
public:
    /** Constrói novo filme com edição do realizador com nome,
	realizador, duração, e alterações dados.
	@pre 0 <= duracao.
	@post nome() = nome e realizador() = realizador e duracao() =
	duracao e alteracoes() = alteracoes. */
    EdicaoDoRealizador(std::string const& nome, std::string const& realizador,
                       int duracao, 
                       std::string const& alteracoes);

    /** Constrói novo filme com edição do realizador com informação
	extraída do canal de entrada. 
	@pre entrada.
	@post *this tem informação extraída do canal de entrada. */
    explicit EdicaoDoRealizador(std::istream& entrada);
    
    /** Devolve as alterações sofridas pelo filme.
	@pre V.
	@post alteracoes = alterações sofridas pelo filme. */
    std::string alteracoes() const;
    
    /** Mostra informação sobre o filme no canal dado num formato
	agradável à vista.
	@pre V.
	@post saida contém a informação sobre o filme. */
    void mostraEm(std::ostream&) const;

    /** Guarda informação sobre o filme no canal dado num formato
	apropriado a futuros carregamentos.
	@pre saida.
	@post saida contém a informação sobre o filme. */
    // void guardaEm(std::ostream&) const;

    /** Le informação sobre o filme do canal dado assumindo que este
	está ligado a um ser humano (e.g., leitura do teclado).
	@pre V.
	@post *this contém a informação sobre o filme lida do canal de
	entrada. */
    // void leDe(std::istream&);

    /** Carrega informação sobre o filme do canal dado assumindo que este
	está ligado no formato usado pela operação carrega().
	@pre entrada.
	@post *this contém a informação sobre o filme carregada do canal de
	entrada. */
    void carregaDe(std::istream&);
    
private:
    std::string alteracoes_;

    /** Indica se a condição invariante da classe se verifica.
	@pre V.
	@post cumpreInvariante = V. */
    bool cumpreInvariante() const;
};

#include "outros_filmes_impl.H"

#endif // OUTROS_FILMES_H