# == Schema Information
# Schema version: 51
#
# Table name: uzytkownik
#
#  uzytkownik_id                    :integer         primary key
#  rola_id                          :integer         not null
#  login                            :text            not null
#  hasz_haslo                       :text            not null
#  sol                              :text            not null
#  imie                             :text            
#  nazwisko                         :text            
#  email                            :text            
#  jak_anotator                     :boolean         
#  created_at                       :timestamp       
#  updated_at                       :timestamp       
#  haslo_updated_at                 :timestamp       
#  tylko_nowe_komentarze_ogladactwo :boolean         default(TRUE)
#  tylko_nowe_komentarze_anotacja   :boolean         
#

 #
 # This file is part of the Anotatornia suite.
 # 
 # Copyright © 2007, 2008, 2009, 2010 by Instytut Podstaw Informatyki
 # Polskiej Akademii Nauk (IPI PAN; Institute of Computer Science, Polish
 # Academy of Sciences; cf. www.ipipan.waw.pl).  All rights reserved.
 # 
 # This file may be distributed and/or modified under the terms of the
 # GNU General Public License version 3 as published by the Free Software
 # Foundation and appearing in the file COPYING included in the packaging
 # of this file.  (See http://www.gnu.org/licenses/translations.html for
 # unofficial translations.)
 # 
 # A commercial license is available from IPI PAN (contact
 # Michal.Ciesiolka.waw.pl or ipi.waw.pl for more
 # information).  Licensees holding a valid commercial license from IPI
 # PAN may use this file in accordance with that license.
 # 
 # This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
 # THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 # PURPOSE.
 #

require 'jcode' # bo #{rake annotate_models} się wywalało na #{jlength}
require 'digest/sha1'

class Uzytkownik < ActiveRecord::Base
  
  # wydaje się nie być technicznych przeciwwskazań do łączenia tej samej bazy użytkowników do dwóch wersji Anotatorni naraz, ale wydaje się być przeciwwskazanie merytoryczne (np. stara Anotatornia ma „śmieciowych” nat1–3, których nowa jako żywo nie potrzebuje.

  ActiveRecord::Base.connection.execute "attach database \"uzytkownicy_#{AnoVersion.port_uzy}.db\" as \"uzy\""
  
  belongs_to :rola

  has_many :transza
  has_many :transze_otwarte, :class_name => "Transza",
  :conditions => ['exists (select * from akapit_transzy akat 
where akat.transza_id = transza.transza_id and akat.status < ? )',
                 AkapitTranszy::STATI[ :zweryfikowany ]]

  has_many :transze_zamkniete, :class_name => "Transza",
  :conditions => ['not exists (select * from akapit_transzy akat 
where akat.transza_id = transza.transza_id and akat.status < ? )',
                 AkapitTranszy::STATI[ :zweryfikowany ]]


  has_many :interpretacja_anot
  has_many :sens_anot

  has_many :odebrania_transz, :class_name => "ProsbyAnotatorek",
  :conditions => {:dotyczy_type => "Transza"}, :order => " updated_at desc, created_at desc "

  has_many :odebrania_odebrane, :class_name => "ProsbyAnotatorek",
  :conditions => {:dotyczy_type => "Transza", :spelniona => true}

  has_one :poziomy_anotacji

  validates_presence_of :login
  validates_uniqueness_of :login

  attr_accessor :haslo_confirmation

  validates_confirmation_of :haslo
  validates_inclusion_of :rola_id, :in => Rola.find(:all).collect {|rola| rola[:rola_id]}

  validates_presence_of :email
  validates_format_of :email, :with => %r{[a-z].*@.*[a-z].*\..*[a-z]}i,
  :message => "musi zawierać literę, @, literę, kropkę i literę."

  def validate
#    errors.add_to_base("Brakuje hasla" ) if @haslo.blank?
    if @haslo # bo nie zawsze uaktualniamy użytkownika z hasłem.
      errors.add_to_base("Hasło musi mieć co najmniej 8 znaków") if @haslo.jlength <8
      # #{require 'jcode'} jest w~\file{application.rb}
      errors.add_to_base("Hasło musi zawierać wielką literę") unless @haslo =~ /[A-Z]/
      errors.add_to_base("Hasło musi zawierać małą literę") unless @haslo =~ /[a-z]/
      errors.add_to_base("Hasło musi zawierać  cyfrę") unless @haslo =~ /[0-9]/
    end
  end
# I could have written the above with the helper methods validates_length_of and validates_format_of
  
  def self.authenticate(login, haslo)
    uzytkownik = self.find_by_login(login)
    if uzytkownik
      haslo_spodziewane = haslo_szyfrowane( haslo, uzytkownik.sol )
      if uzytkownik.hasz_haslo != haslo_spodziewane
        uzytkownik = nil
      elsif uzytkownik.rola_id == Rola.rid( :zablokowany )
        uzytkownik = :zablokowany
      end
    end
    uzytkownik
  end
  
  # 'password' is a virtual attribute
  def haslo
    @haslo
  end

  def stare_haslo
    #tylko po to, żeby tworzył się formularz zmiany hasła
  end

  def haslo=(pwd)
    @haslo = pwd
    zrob_nowa_sol
    self.hasz_haslo = Uzytkownik.haslo_szyfrowane(self.haslo, self.sol)
  end

  def after_create
    PoziomyAnotacji.nadąż_za_użytkownikiem
  end
  
  def after_destroy
    if Uzytkownik.find(:all, :conditions => {:rola_id => Rola.rid(:admin) }).size.zero?
      raise "Nie usunę ostatniego admina."
    else
      PoziomyAnotacji.nadąż_za_użytkownikiem
    end
  end

  def after_update
    if Uzytkownik.find(:all, :conditions => {:rola_id => Rola.rid(:admin) }).size.zero?
      raise "Nie zablokuję ostatniego admina."
    end
  end

  
  def anotator?
    Rola.ktoras_z_rol?(self, :anotator)
  end
  
  def zarzadca?
    Rola.ktoras_z_rol?(self, :zarzadca)
  end

  def ktoras_z_rol?( *role )
    Rola.ktoras_z_rol?(self, *role )
  end

  def transza_ids
    self.transza.collect{ |tra| tra.id }
  end

  def ile_zakończonych
    AkapitTranszy.ile_zaanotowanych( {:transza_id => self.transza_ids}, :zakończony )
  end

  def ile_oczekujących
    AkapitTranszy.ile_zaanotowanych( {:transza_id => self.transza_ids}, :oczekujące )
  end

  def ile_anotaśnych
    AkapitTranszy.ile_zaanotowanych( {:transza_id => self.transza_ids}, :anotaśne )
  end


  def no_record?( tab_symb )
    uid = self.uzytkownik_id
    if tab_symb == :statusy
      where = PoziomyAnotacji.poziomy_x.collect {|poz|
        " #{poz}_uzid = #{uid} "}.
        join(" or " )
      
    else
      where = " uzytkownik_id = #{uid} "
    end
    
    tab_symb.to_s.camelize.constantize.find_by_sql( 
                                                   "select count(*) as cnt from #{tab_symb.to_s} " +
                                                   " where #{where}"
                                                   )[0].cnt.to_i == 0
  end # of #no_record?
  

  def self.natror
    self.find_by_login( 'natror' )
  end

  
  def ile_transz_zakończonych( poziom = :max )

    where_poziom202 = 
      if poziom == :max
        PoziomyAnotacji.maksymalne & PoziomyAnotacji.działające
      else
        [ poziom ]
      end .
      collect { |po202|
      "#{po202}<=#{Statusy::STATI[ :po_poprawce ]}"
    }.join( ' or ' ) # wszystko musi być na odwrót (po de Morganowsku), bo idzie do klauzuli \sql{not exists}.

    Transza.count_by_sql( 
                         "select count(*) from transza where uzytkownik_id=#{self.id}" +
                         " and not exists (select 1 from statusy s where " +
                         " s.transza_id=transza.transza_id and " +
                         " #{where_poziom202})"
                         )

  end # of #{ile_transz_zakończonych}


  private

  def self.haslo_szyfrowane(haslo, sol)
    string_to_hash = haslo + "wyswi17" + sol # 'wibble' makes it harder to guess
    Digest::SHA1.hexdigest( string_to_hash )
  end
  
  def zrob_nowa_sol
    self.sol = self.object_id.to_s + rand.to_s
  end

  
  def self.natrorize
    if UNatrora.x
      
      self.find(:all, 
                :conditions => " login not like 'natror%' and login <>'QueenOfSpades' " 
                ).each{ |uzytkownik|
        haslo= uzytkownik.login + '666aA'
        uzytkownik.haslo =   haslo
        uzytkownik.haslo_confirmation=haslo
        if  uzytkownik.save!
          ##          puts "Zmieniłam hasło użytkownika #{uzytkownik.login} na '#{haslo}'."
        end
      }
      puts "Zmieniłam hasła użytkowników na »<login>666aA«"
    end # of #{if UNatrora.x}
  end # of #{self.natrorize}
  
  # if we are in a virgin database, we create a dummy admin to allow
  # new licensee to add their own users.
  if self.count == 0
    self.create!(
                 :login => "QueenOfSpades",
                 :hasz_haslo => '1467fdaf0fe9be193e02f053cd39788224d2741e', 
                 # "15 mars 1615 Paris"
                 :sol => '-6098396180.298015019238499',
                 :imie => 'Marguerite',
                 :nazwisko => 'de France et Navarre',
                 :email => 'margot@louvre.fr',
                 :rola_id => Rola.rid( :admin ),
                 :tylko_nowe_komentarze_ogladactwo => true,
                 :tylko_nowe_komentarze_anotacja => true,
                 :jak_anotator => false
                 )
  end

  natrorize if UNatrora.x
  # #{make_natrors} removed for security reasons to \file{anotatornia-trash/natrory.rb} (not available in this version). Equivalent (and also not available here) \ac{SQL} inserts are in \file{anotatornia-trash/natrory.sql}.
  PoziomyAnotacji.nadąż_za_użytkownikiem
  true


end # of class



### Local Variables: 
### mode: ruby
### End:
