#!/usr/bin/env python
# coding=utf8
import sys
from subprocess import call,Popen,PIPE
from os.path import abspath,join,dirname,basename
from tempfile import NamedTemporaryFile

def decoupe_entree(ligne):
  elements=ligne.split(None,8)
  entree={
    "droits"      :elements[0],
    "proprietaire":elements[2],
    "groupe"      :elements[3],
    "contexte"    :elements[4],
    "taille"      :elements[5],
    "jour"        :elements[6],
    "heure"       :elements[7],
    "nom"         :elements[8]
  }

  lettre_type=elements[0][0]
  entree["type"]="fichier de type inconnu"
  if lettre_type=="d": entree["type"]="répertoire"
  if lettre_type=="-": entree["type"]="fichier"
  if lettre_type=="b": entree["type"]="fichier bloc spécial"
  if lettre_type=="c": entree["type"]="fichier caractère spécial"
  if lettre_type=="l": entree["type"]="lien symbolique"
  if lettre_type=="p": entree["type"]="tube nommé"
  if lettre_type=="s": entree["type"]="socket"

  return entree

def exec_analyse(repertoires):
  cmd1=['ls','-AlRZ','--time-style=long-iso']+repertoires
  cmd2=['grep','-v','-e','^total','-e','^$']

  p1=Popen(cmd1,stdout=PIPE,stderr=PIPE)
  p2=Popen(cmd2,stdin=p1.stdout,stdout=PIPE,stderr=None)

  lignes=p2.communicate()[0].splitlines()

  repcourant=""
  entrees   ={}
  for ligne in lignes:
    if ligne.startswith("/"):
      repcourant=ligne[0:-1]
    else:
      entree=decoupe_entree(ligne)
      entrees[join(repcourant,entree['nom'])]=entree

  return entrees

def compare_entree(avant,apres):
  differences=[]
  comparaisons={
    "type"        : "le type a changé",
    "proprietaire": "le propriétaire a changé",
    "groupe"      : "le groupe a changé",
    "contexte"    : "le contexte SELinux a changé",
    "taille"      : "la taille a changé",
    "jour"        : "la date de modification a changé",
    "heure"       : "l’heure de modification a changé"
  }

  for composant in comparaisons:
    if avant[composant]!=apres[composant]:
      differences.append(comparaisons[composant]+" (%s → %s)"%(avant[composant],apres[composant]))

  return differences

def compare_entrees(entrees_avant,entrees_apres):
  ajouts       =[]
  suppressions =[]
  modifications=[]

  # Recherche les suppressions et les modifications
  for entree in entrees_avant:
    if entree not in entrees_apres:
      # Entrée supprimée
      suppressions.append(entree)
      continue

    if entrees_avant[entree]!=entrees_apres[entree]:
      # Entrées différentes
      modifications.append(entree)

  # Recherche les ajouts:
  for entree in entrees_apres:
    if entree not in entrees_avant:
      # Nouvelle entrée
      ajouts.append(entree)

  return [ajouts,suppressions,modifications]

def prepare_nom(chemin):
  chemin=chemin.replace("&","&amp;").replace(">","&gt;").replace("<","&tt;")
  return dirname(chemin)+"/<strong>"+basename(chemin)+"</strong>"

def affiche_differences(entrees_avant,entrees_apres,ajouts,suppressions,modifications):
  html ='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">\n'
  html+='<html lang="fr">\n'

  html+='<head>\n'
  html+='<title>Suivi des modifications</title>\n'
  html+='<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\n'
  html+='</head>\n'

  html+='<body>\n'
  html+='<h1>Suivi des modifications</h1>'

  html+='<h2>Ajouts</h2>\n'
  if len(ajouts)==0:
    html+='<p>Aucun ajout</p>\n'
  else:
    html+='<ul>\n'
    for ajout in ajouts:
      html+='<li>'+prepare_nom(ajout)+' (<i>'+entrees_apres[ajout]["type"]+'</i>)</li>\n'
    html+='</ul>\n'

  html+='<h2>Suppressions</h2>\n'
  if len(suppressions)==0:
    html+='<p>Aucune suppression</p>\n'
  else:
    html+='<ul>\n'
    for suppression in suppressions:
      html+='<li>'+prepare_nom(suppression)+' (<i>'+entrees_avant[suppression]["type"]+'</i>)</li>\n'
    html+='</ul>\n'

  html+='<h2>Modifications</h2>\n'
  if len(modifications)==0:
    html+='<p>Aucune modification</p>\n'
  else:
    html+='<ul>\n'
    for modification in modifications:
      html+='<li>'+prepare_nom(modification)
      diffs=compare_entree(entrees_avant[modification],entrees_apres[modification])
      html+='<ul>\n'
      for diff in diffs:
        html+='<li>'+diff+'</li>\n'
      html+="</ul>\n"
      html+='</li>\n'
    html+='</ul>\n'

  html+='</body>\n'
  html+='</html>'

  return html  

if len(sys.argv)>=2:
  rep_donnes=sys.argv[1:]
else:
  rep_donnes=Popen(['zenity','--file-selection','--directory','--multiple'],stdout=PIPE).communicate()[0].splitlines()[0]
  if rep_donnes=="": exit(0)
  rep_donnes=rep_donnes.split('|')

repertoires=[]
for rep in rep_donnes:
  rep=rep.strip()
  if rep=="": continue
  rep=abspath(rep)
  if rep in repertoires: continue
  repertoires.append(abspath(rep))

if len(repertoires)==0: exit(0)

entrees_avant=exec_analyse(repertoires)

call(["zenity","--info","--title=Premier cliché réalisé","--text=Un premier cliché du répertoire a été réalisé.\nVeuillez cliquer sur le bouton pour lancer le second et afficher les différences"])

entrees_apres=exec_analyse(repertoires)

(ajouts,suppressions,modifications)=compare_entrees(entrees_avant,entrees_apres)

html=affiche_differences(entrees_avant,entrees_apres,ajouts,suppressions,modifications)
sortie=NamedTemporaryFile(suffix=".html")
sortie.write(html)
sortie.flush()
call(["yelp",sortie.name])
