#!/usr/bin/env python2.4
#
# Copyright 2007 Google Inc.
#
# 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.

import binascii
import base64
import sha
import zlib
import getpass
import logging
import optparse
import os
import re
import sys
from xml.dom.minidom import parseString
from pyPgSQL import PgSQL
from pyPgSQL.libpq import PgQuoteBytea, OperationalError

from codereview.proto_client import HttpRpc, Proxy
from codereview.backup_pb2 import *

KINDS = [
  "ApprovalRight",
  "Project",
  "Branch",
  "RevisionId",
  "Change",
  "PatchSet",
  "Message",
  "DeltaContent",
  "Patch",
  "Comment",
  "ReviewStatus",
  "Account",
  "AccountGroup",
]
[
  "Settings",
  "BuildAttempt",
  "PatchSetFilenames",
  "Bucket",
]

try:
  import readline
except ImportError:
  pass

parser = optparse.OptionParser(usage="%prog [options] [-- diff_options]")

# Review server
group = parser.add_option_group("Review server options")
group.add_option("-s", "--server", action="store", dest="server",
                 default="codereview.appspot.com",
                 metavar="SERVER",
                 help=("The server to upload to. The format is host[:port]. "
                       "Defaults to 'codereview.appspot.com'."))
group.add_option("-e", "--email", action="store", dest="email",
                 metavar="EMAIL", default=None,
                 help="The username to use. Will prompt if omitted.")
group.add_option("-H", "--host", action="store", dest="host",
                 metavar="HOST", default=None,
                 help="Overrides the Host header sent with all RPCs.")
group.add_option("--no_cookies", action="store_false",
                 dest="save_cookies", default=True,
                 help="Do not save authentication cookies to local disk.")

group = parser.add_option_group("Backup database options")
group.add_option('-v', action='store', dest='last_backed_up',
                 default=0,
                 help='Value for last_backed_up query')
group.add_option("-d", action="store", dest="dbname",
                 metavar="DBNAME",
                 help="PostgreSQL database name")

def GetRpcServer(options):
  def GetUserCredentials():
    email = options.email
    if email is None:
      email = raw_input("Email: ").strip()
    password = getpass.getpass("Password for %s: " % email)
    return (email, password)

  host = (options.host or options.server).lower()
  if host == "localhost" or host.startswith("localhost:"):
    email = options.email
    if email is None:
      email = "test@example.com"
      logging.info("Using debug user %s.  Override with --email" % email)

    server = HttpRpc(
        options.server,
        lambda: (email, "password"),
        host_override=options.host,
        extra_headers={"Cookie":
                       'dev_appserver_login="%s:False"' % email})
    server.authenticated = True
    return server

  if options.save_cookies:
    cookie_file = ".gerrit_cookies"
  else:
    cookie_file = None

  return HttpRpc(options.server, GetUserCredentials,
                 host_override=options.host,
                 cookie_file=cookie_file)

def getText(nodelist):
  rc = ""
  for node in nodelist:
    if node.nodeType == node.TEXT_NODE:
      rc = rc + node.data
  return rc

key_re = re.compile(r'^tag:.*\[(.*)\]$')

def parse_dom(dom):
  class AnyObject(object):
    def __getattr__(self, name):
      return []

  o = AnyObject()
  for p in dom.getElementsByTagName('property'):
    n = p.getAttribute('name')
    v = getText(p.childNodes)
    t = p.getAttribute('type')
    if t == 'null':
      continue

    if t == 'key':
      v = key_re.match(v).group(1)
    elif t == 'int':
      v = int(v)
    elif t == 'bool':
      if v == 'True':
        v = True
      elif v == 'False':
        v = False
    elif t == 'gd:email':
      v = p.getElementsByTagName('gd:email')[0].getAttribute('address')
      if v and '@' not in v:
        v += '@gmail.com'
    elif t == 'user':
      if v and '@' not in v:
        v += '@gmail.com'

    a = getattr(o, n, [])
    if v != '':
      a.append(v)
    setattr(o, n, a)
  return o

def one(v):
  if len(v) == 1:
    return v[0]
  return None

def yn(v):
  if one(v):
    return 'Y'
  return 'N'

def yn_null(v):
  if len(v) == 1 and v[0] is not None:
    return yn(v)
  return None


class LocalStore(object):
  def __init__(self, db):
    self.db = db

  def delete(self, table_name, entity):
    c = self.db.cursor()
    c.execute('DELETE FROM ' + table_name + ' WHERE gae_key=%s',
              (entity.key))

  def insert(self, table_name, dict, base64_keys=[]):
    p = []
    for u in dict.keys():
      if u in base64_keys:
        p.append("decode(%s,'base64')")
      else:
        p.append('%s')

    s = 'INSERT INTO ' + table_name + '(' + ','.join(dict.keys()) + ')'
    s += 'VALUES(' + ','.join(p) + ')'
    c = self.db.cursor()
    try:
      c.execute(s, dict.values())
    except OperationalError:
      print 'FAIL %s %s' % (table_name, dict)
      raise

  def save_ApprovalRight(self, entity, obj):
    ar_id = entity.key_id
    self.delete('approval_rights', entity)
    self.insert('approval_rights', {
      'ar_id': ar_id,
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),

      'required': yn(obj.required),
    })

    for p in obj.files:
      self.insert('approval_right_files', {'ar_id':ar_id, 'path':p})

    for u in obj.approvers_users:
      self.insert('approval_right_users', {'ar_id':ar_id, 'email':u, 'type': 'approver'})
    for u in obj.verifiers_users:
      self.insert('approval_right_users', {'ar_id':ar_id, 'email':u, 'type': 'verifier'})
    for u in obj.submitters_users:
      self.insert('approval_right_users', {'ar_id':ar_id, 'email':u, 'type': 'submitter'})

    for u in obj.approvers_groups:
      self.insert('approval_right_groups', {'ar_id':ar_id, 'group_key':u, 'type': 'approver'})
    for u in obj.verifiers_groups:
      self.insert('approval_right_groups', {'ar_id':ar_id, 'group_key':u, 'type': 'verifier'})
    for u in obj.submitters_groups:
      self.insert('approval_right_groups', {'ar_id':ar_id, 'group_key':u, 'type': 'submitter'})

  def save_Project(self, entity, obj):
    project_id = entity.key_id
    self.delete('projects', entity)
    self.insert('projects', {
      'project_id': project_id,
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),

      'name': one(obj.name),
      'comment': one(obj.comment),
    })

    for u in obj.owners_users:
      self.insert('project_owner_users', {'project_id':project_id, 'email':u})
    for u in obj.owners_groups:
      self.insert('project_owner_groups', {'project_id':project_id, 'group_key':u})
    for u in obj.code_reviews:
      self.insert('project_code_reviews', {'project_id':project_id, 'ar_key':u})

  def save_Branch(self, entity, obj):
    self.delete('branches', entity)
    self.insert('branches', {
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),
      'project_key': one(obj.project),
      'name': one(obj.name),
    })

  def save_RevisionId(self, entity, obj):
    self.delete('revisions', entity)
    self.insert('revisions', {
      'revision_id': one(obj.id),
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),
      'project_key': one(obj.project),

      'author_name': one(obj.author_name),
      'author_email': one(obj.author_email),
      'author_when': one(obj.author_when),
      'author_tz': one(obj.author_tz),

      'committer_name': one(obj.committer_name),
      'committer_email': one(obj.committer_email),
      'committer_when': one(obj.committer_when),
      'committer_tz': one(obj.committer_tz),

      'message': one(obj.message),
      'patchset_key': one(obj.patchset_key),
    })

    p = 1
    for a in obj.ancestors:
      self.insert('revision_ancestors', {
        'gae_key': entity.key,
        'child_id': one(obj.id),
        'parent_id': a,
        'position': p})
      p += 1

  def save_Change(self, entity, obj):
    change_id = entity.key_id
    self.delete('changes', entity)
    self.insert('changes', {
      'last_backed_up': one(obj.last_backed_up),
      'gae_key': entity.key,
      'change_id': change_id,
      'subject': one(obj.subject),
      'description': one(obj.description),
      'owner': one(obj.owner),
      'created': one(obj.created),
      'modified': one(obj.modified),
      'claimed': yn(obj.claimed),
      'closed': yn(obj.closed),
      'n_comments': one(obj.n_comments),
      'n_patchsets': one(obj.n_patchsets),
      'dest_project_key': one(obj.dest_project),
      'dest_branch_key': one(obj.dest_branch),
      'merge_submitted': one(obj.merge_submitted),
      'merged': yn(obj.merged),
      'emailed_clean_merge': yn(obj.emailed_clean_merge),
      'emailed_missing_dependency': yn(obj.emailed_missing_dependency),
      'emailed_path_conflict': yn(obj.emailed_path_conflict),
      'merge_patchset_key': one(obj.merge_patchset_key),
    })
    
    for u in obj.reviewers:
      self.insert('change_people', {'change_id':change_id,'email':u,'type':'reviewer'})
    for u in obj.cc:
      self.insert('change_people', {'change_id':change_id,'email':u,'type':'cc'})

  def save_PatchSet(self, entity, obj):
    self.delete('patch_sets', entity)
    self.insert('patch_sets', {
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),
      'patchset_id': one(obj.id),
      'change_key': one(obj.change),
      'message': one(obj.message),
      'owner': one(obj.owner),
      'created': one(obj.created),
      'modified': one(obj.modified),
      'revision_key': one(obj.revision),
      'complete': yn(obj.complete),
    })

  def save_Message(self, entity, obj):
    self.delete('messages', entity)
    self.insert('messages', {
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),
      'change_key': one(obj.change),
      'subject': one(obj.subject),
      'sender': one(obj.sender),
      'date_sent': one(obj.date),
      'body': one(obj.text),
    })

    for u in obj.recipients:
      self.insert('message_recipients', {'message_key':entity.key,'email':u})

  def save_DeltaContent(self, entity, obj):
    type, hash = entity.key_name.split(':')

    self.delete('delta_content', entity)
    self.insert('delta_content', {
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),
      'type': type,
      'hash': hash,
      'data_z': one(obj.text_z),
      'depth': one(obj.depth),
      'base_key': one(obj.base),
    }, set(['data_z']))

  def save_Patch(self, entity, obj):
    self.delete('patches', entity)
    self.insert('patches', {
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),
      'patchset_key': one(obj.patchset),
      'filename': one(obj.filename),
      'status': one(obj.status),
      'multi_way_diff': yn(obj.multi_way_diff),
      'n_comments': one(obj.n_comments),
      'old_data_key': one(obj.old_data),
      'new_data_key': one(obj.new_data),
      'diff_data_key': one(obj.diff_data),
    })

  def save_Comment(self, entity, obj):
    self.delete('comments', entity)
    self.insert('comments', {
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),
      'patch_key': one(obj.patch),
      'message_id': one(obj.message_id),
      'author': one(obj.author),
      'written': one(obj.date),
      'lineno': one(obj.lineno),
      'body': one(obj.text),
      'is_left': yn(obj.left),
      'draft': yn(obj.draft),
    })

  def save_ReviewStatus(self, entity, obj):
    self.delete('review_status', entity)
    self.insert('review_status', {
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),
      'change_key': one(obj.change),
      'email': one(obj.user),
      'lgtm': one(obj.lgtm),
      'verified': yn_null(obj.verified),
    })

  def save_Account(self, entity, obj):
    email = entity.key_name
    if email.startswith('<'):
      email = email[1:]
    if email.endswith('>'):
      email = email[:-1]
    if '@' not in email:
      email += '@gmail.com'

    self.delete('accounts', entity)
    self.insert('accounts', {
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),

      'user_email': one(obj.user),
      'email': email,
      'preferred_email': one(obj.preferred_email),
      'created': one(obj.created),
      'modified': one(obj.modified),

      'is_admin': yn(obj.is_admin),
      'welcomed': yn(obj.welcomed),
      'real_name_entered': yn(obj.real_name_entered),
      'real_name': one(obj.real_name),
      'mailing_address': one(obj.mailing_address),
      'mailing_address_country': one(obj.mailing_address_country),
      'phone_number': one(obj.phone_number),
      'fax_number': one(obj.fax_number),

      'cla_verified': yn(obj.cla_verified),
      'cla_verified_by': one(obj.cla_verified_by),
      'cla_verified_timestamp': one(obj.cla_verified_timestamp),
      'individual_cla_version': one(obj.individual_cla_version),
      'individual_cla_timestamp': one(obj.individual_cla_timestamp),
      'cla_comments': one(obj.cla_comments),

      'default_context': one(obj.default_context),
    })

    for i in set(obj.stars):
      self.insert('account_stars', {'email':email,'change_id':i})
    for i in set(obj.unclaimed_changes_projects):
      self.insert('account_unclaimed_changes_projects', {'email':email,'project_key':i})

  def save_AccountGroup(self, entity, obj):
    self.delete('account_groups', entity)
    self.insert('account_groups', {
      'gae_key': entity.key,
      'last_backed_up': one(obj.last_backed_up),
      'name': one(obj.name),
      'comment': one(obj.comment),
    })

    for i in set(obj.members):
      self.insert('account_group_users', {'group_name':one(obj.name),'email':i})

def RealMain(argv, data=None):
  os.environ['LC_ALL'] = 'C'
  options, args = parser.parse_args(argv[1:])

  srv = GetRpcServer(options)
  backup = Proxy(BackupService_Stub(srv))
  db = PgSQL.connect(database=options.dbname,
                     client_encoding="utf-8",
                     unicode_results=1)
  db.cursor().execute("set client_encoding to unicode")

  store = LocalStore(db)
  last_backed_up = int(options.last_backed_up)

  print 'BEGIN BACKUP %d' % last_backed_up
  for kind_name in KINDS:
    sys.stdout.write('\n')
    cnt = 0

    while True:
      sys.stdout.write('\r%-18s ... ' % kind_name)
      r = NextChunkRequest()
      r.kind = kind_name
      r.last_backed_up = last_backed_up
      
      r = backup.NextChunk(r)
      if not r.entity:
        break

      ack = AckChunkRequest()
      ack.last_backed_up = last_backed_up + 1
      for entity in r.entity:
        cnt += 1
        sys.stdout.write('\r%-18s ... %5d ' % (kind_name, cnt))

        o = parse_dom(parseString(
          '<?xml version="1.0" encoding="utf-8"?>'
          '<root xmlns:gd="http://www.google.com/">'
          '%s'
          '</root>'
          % entity.xml))
        getattr(store, 'save_%s' % kind_name)(entity, o)
        a = ack.entity.add()
        a.key = entity.key
        a.last_backed_up = entity.last_backed_up
      db.commit()
      backup.AckChunk(ack)

  sys.stdout.write('\n')
  print 'BACKUP %d DONE' % last_backed_up
  db.commit()
  db.close()


def main():
  try:
    RealMain(sys.argv)
  except KeyboardInterrupt:
    print
    print "Interrupted."
    sys.exit(1)


if __name__ == "__main__":
  main()
