# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd

"""Servlet to safely display textual issue attachments.

Unlike most attachments, this is not a download, it is a full HTML page
with safely escaped user content.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging

import ezt
from google.appengine.api import app_identity
from google.cloud import storage

from features import prettify
from framework import exceptions
from framework import flaskservlet
from framework import filecontent
from framework import permissions
from framework import servlet
from framework import template_helpers
from tracker import attachment_helpers
from tracker import tracker_bizobj
from tracker import tracker_helpers


class AttachmentText(servlet.Servlet):
  """AttachmentText displays textual attachments much like source browsing."""

  _PAGE_TEMPLATE = 'tracker/issue-attachment-text.ezt'
  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_ISSUES

  def GatherPageData(self, mr):
    """Parse the attachment ID from the request and serve its content.

    Args:
      mr: commonly used info parsed from the request.

    Returns:
      Dict of values used by EZT for rendering almost the page.
    """
    with mr.profiler.Phase('get issue, comment, and attachment'):
      try:
        attachment, issue = tracker_helpers.GetAttachmentIfAllowed(
            mr, self.services)
      except exceptions.NoSuchIssueException:
        self.abort(404, 'issue not found')
      except exceptions.NoSuchAttachmentException:
        self.abort(404, 'attachment not found')
      except exceptions.NoSuchCommentException:
        self.abort(404, 'comment not found')

    content = b''
    if attachment.gcs_object_id:
      bucket_name = app_identity.get_default_gcs_bucket_name()
      full_path = '/' + bucket_name + attachment.gcs_object_id
      logging.info("reading gcs: %s" % full_path)

      # Strip leading slash from object ID for backwards compatibility.
      blob_name = attachment.gcs_object_id
      if blob_name.startswith('/'):
        blob_name = blob_name[1:]

      client = storage.Client()
      bucket = client.get_bucket(bucket_name)
      blob = bucket.get_blob(blob_name)
      content = blob.download_as_bytes()

    filesize = len(content)

    # This servlet only displays safe textual attachments. The user should
    # not have been given a link to this servlet for any other kind.
    if not attachment_helpers.IsViewableText(attachment.mimetype, filesize):
      self.abort(400, 'not a text file')

    u_text, is_binary, too_large = filecontent.DecodeFileContents(content)
    lines = prettify.PrepareSourceLinesForHighlighting(u_text.encode('utf8'))

    config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
    granted_perms = tracker_bizobj.GetGrantedPerms(
        issue, mr.auth.effective_ids, config)
    page_perms = self.MakePagePerms(
        mr, issue, permissions.DELETE_ISSUE, permissions.CREATE_ISSUE,
        granted_perms=granted_perms)

    page_data = {
        'issue_tab_mode': 'issueDetail',
        'local_id': issue.local_id,
        'filename': attachment.filename,
        'filesize': template_helpers.BytesKbOrMb(filesize),
        'file_lines': lines,
        'is_binary': ezt.boolean(is_binary),
        'too_large': ezt.boolean(too_large),
        'code_reviews': None,
        'page_perms': page_perms,
        }
    if is_binary or too_large:
      page_data['should_prettify'] = ezt.boolean(False)
    else:
      page_data.update(prettify.BuildPrettifyData(
          len(lines), attachment.filename))

    return page_data

  # def GetAttachmentText(self, **kwargs):
  #   return self.handler(**kwargs)
