<%inherit file="/base/base.mako"/>

<%def name="title()">
    ${c.repo_name} ${_('New pull request')}
</%def>

<%def name="breadcrumbs_links()">
    ${_('New pull request')}
</%def>

<%def name="menu_bar_nav()">
    ${self.menu_items(active='repositories')}
</%def>

<%def name="menu_bar_subnav()">
    ${self.repo_menu(active='showpullrequest')}
</%def>

<%def name="main()">
<div class="box">
    <div class="title">
        ${self.repo_page_title(c.rhodecode_db_repo)}
        ${self.breadcrumbs()}
    </div>

    ${h.secure_form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
        <div class="box pr-summary">

            <div class="summary-details block-left">

                <div class="form">
                    <!-- fields -->

                    <div class="fields" >

                         <div class="field">
                            <div class="label">
                                <label for="pullrequest_title">${_('Title')}:</label>
                            </div>
                            <div class="input">
                                ${h.text('pullrequest_title', c.default_title, class_="medium autogenerated-title")}
                            </div>
                         </div>

                        <div class="field">
                            <div class="label label-textarea">
                                <label for="pullrequest_desc">${_('Description')}:</label>
                            </div>
                            <div class="textarea text-area editor">
                                ${h.textarea('pullrequest_desc',size=30, )}
                                <span class="help-block">${_('Write a short description on this pull request')}</span>
                            </div>
                        </div>

                        <div class="field">
                            <div class="label label-textarea">
                                <label for="pullrequest_desc">${_('Commit flow')}:</label>
                            </div>

                            ## TODO: johbo: Abusing the "content" class here to get the
                            ## desired effect. Should be replaced by a proper solution.

                            ##ORG
                            <div class="content">
                                <strong>${_('Origin repository')}:</strong>
                                ${c.rhodecode_db_repo.description}
                            </div>
                            <div class="content">
                                ${h.hidden('source_repo')}
                                ${h.hidden('source_ref')}
                            </div>

                            ##OTHER, most Probably the PARENT OF THIS FORK
                            <div class="content">
                                ## filled with JS
                                <div id="target_repo_desc"></div>
                            </div>

                            <div class="content">
                                ${h.hidden('target_repo')}
                                ${h.hidden('target_ref')}
                                <span id="target_ref_loading" style="display: none">
                                    ${_('Loading refs...')}
                                </span>
                            </div>
                        </div>

                        <div class="field">
                            <div class="label label-textarea">
                                <label for="pullrequest_submit"></label>
                            </div>
                            <div class="input">
                                <div class="pr-submit-button">
                                    ${h.submit('save',_('Submit Pull Request'),class_="btn")}
                                </div>
                                <div id="pr_open_message"></div>
                            </div>
                        </div>

                        <div class="pr-spacing-container"></div>
                    </div>
                </div>
            </div>
            <div>
                <div class="reviewers-title block-right">
                    <div class="pr-details-title">
                        ${_('Pull request reviewers')}
                        <span class="calculate-reviewers"> - ${_('loading...')}</span>
                    </div>
                </div>
                <div id="reviewers" class="block-right pr-details-content reviewers">
                    ## members goes here, filled via JS based on initial selection !
                    <input type="hidden" name="__start__" value="review_members:sequence">
                    <ul id="review_members" class="group_members"></ul>
                    <input type="hidden" name="__end__" value="review_members:sequence">
                    <div id="add_reviewer_input" class='ac'>
                        <div class="reviewer_ac">
                            ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
                            <div id="reviewers_container"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="box">
            <div>
                ## overview pulled by ajax
                <div id="pull_request_overview"></div>
            </div>
        </div>
    ${h.end_form()}
</div>

<script type="text/javascript">
$(function(){
  var defaultSourceRepo = '${c.default_repo_data['source_repo_name']}';
  var defaultSourceRepoData = ${c.default_repo_data['source_refs_json']|n};
  var defaultTargetRepo = '${c.default_repo_data['target_repo_name']}';
  var defaultTargetRepoData = ${c.default_repo_data['target_refs_json']|n};
  var targetRepoName = '${c.repo_name}';

  var $pullRequestForm = $('#pull_request_form');
  var $sourceRepo = $('#source_repo', $pullRequestForm);
  var $targetRepo = $('#target_repo', $pullRequestForm);
  var $sourceRef = $('#source_ref', $pullRequestForm);
  var $targetRef = $('#target_ref', $pullRequestForm);

  var calculateContainerWidth = function() {
      var maxWidth = 0;
      var repoSelect2Containers = ['#source_repo', '#target_repo'];
      $.each(repoSelect2Containers, function(idx, value) {
          $(value).select2('container').width('auto');
          var curWidth = $(value).select2('container').width();
          if (maxWidth <= curWidth) {
              maxWidth = curWidth;
          }
          $.each(repoSelect2Containers, function(idx, value) {
              $(value).select2('container').width(maxWidth + 10);
          });
      });
  };

  var initRefSelection = function(selectedRef) {
      return function(element, callback) {
          // translate our select2 id into a text, it's a mapping to show
          // simple label when selecting by internal ID.
          var id, refData;
          if (selectedRef === undefined) {
            id = element.val();
            refData = element.val().split(':');
          } else {
            id = selectedRef;
            refData = selectedRef.split(':');
          }

          var text = refData[1];
          if (refData[0] === 'rev') {
              text = text.substring(0, 12);
          }

          var data = {id: id, text: text};

          callback(data);
      };
  };

  var formatRefSelection = function(item) {
      var prefix = '';
      var refData = item.id.split(':');
      if (refData[0] === 'branch') {
          prefix = '<i class="icon-branch"></i>';
      }
      else if (refData[0] === 'book') {
          prefix = '<i class="icon-bookmark"></i>';
      }
      else if (refData[0] === 'tag') {
          prefix = '<i class="icon-tag"></i>';
      }

      var originalOption = item.element;
      return prefix + item.text;
  };

  // custom code mirror
  var codeMirrorInstance = initPullRequestsCodeMirror('#pullrequest_desc');

  var queryTargetRepo = function(self, query) {
      // cache ALL results if query is empty
      var cacheKey = query.term || '__';
      var cachedData = self.cachedDataSource[cacheKey];

      if (cachedData) {
          query.callback({results: cachedData.results});
      } else {
          $.ajax({
              url: pyroutes.url('pullrequest_repo_destinations', {'repo_name': targetRepoName}),
              data: {query: query.term},
              dataType: 'json',
              type: 'GET',
              success: function(data) {
                  self.cachedDataSource[cacheKey] = data;
                  query.callback({results: data.results});
              },
              error: function(data, textStatus, errorThrown) {
                  alert(
                    "Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
              }
          });
      }
  };

  var queryTargetRefs = function(initialData, query) {
      var data = {results: []};
      // filter initialData
      $.each(initialData, function() {
          var section = this.text;
          var children = [];
          $.each(this.children, function() {
              if (query.term.length === 0 ||
                  this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ) {
                  children.push({'id': this.id, 'text': this.text})
              }
          });
          data.results.push({'text': section, 'children': children})
      });
      query.callback({results: data.results});
  };


  var prButtonLockChecks = {
      'compare': false,
      'reviewers': false
  };

  var prButtonLock = function(lockEnabled, msg, scope) {
      scope = scope || 'all';
      if (scope == 'all'){
          prButtonLockChecks['compare'] = !lockEnabled;
          prButtonLockChecks['reviewers'] = !lockEnabled;
      } else if (scope == 'compare') {
          prButtonLockChecks['compare'] = !lockEnabled;
      } else if (scope == 'reviewers'){
          prButtonLockChecks['reviewers'] = !lockEnabled;
      }
      var checksMeet = prButtonLockChecks.compare && prButtonLockChecks.reviewers;
      if (lockEnabled) {
          $('#save').attr('disabled', 'disabled');
      }
      else if (checksMeet) {
          $('#save').removeAttr('disabled');
      }

      if (msg) {
          $('#pr_open_message').html(msg);
      }
  };

  var loadRepoRefDiffPreview = function() {
      var sourceRepo = $sourceRepo.eq(0).val();
      var sourceRef = $sourceRef.eq(0).val().split(':');

      var targetRepo = $targetRepo.eq(0).val();
      var targetRef = $targetRef.eq(0).val().split(':');

      var url_data = {
          'repo_name': targetRepo,
          'target_repo': sourceRepo,
          'source_ref': targetRef[2],
          'source_ref_type': 'rev',
          'target_ref': sourceRef[2],
          'target_ref_type': 'rev',
          'merge': true,
          '_': Date.now() // bypass browser caching
      }; // gather the source/target ref and repo here

      if (sourceRef.length !== 3 || targetRef.length !== 3) {
          prButtonLock(true, "${_('Please select origin and destination')}");
          return;
      }
      var url = pyroutes.url('compare_url', url_data);

      // lock PR button, so we cannot send PR before it's calculated
      prButtonLock(true, "${_('Loading compare ...')}", 'compare');

      if (loadRepoRefDiffPreview._currentRequest) {
          loadRepoRefDiffPreview._currentRequest.abort();
      }

      loadRepoRefDiffPreview._currentRequest = $.get(url)
          .error(function(data, textStatus, errorThrown) {
                alert(
                "Error while processing request.\nError code {0} ({1}).".format(
                        data.status, data.statusText));
          })
          .done(function(data) {
              loadRepoRefDiffPreview._currentRequest = null;
              $('#pull_request_overview').html(data);
              var commitElements = $(data).find('tr[commit_id]');

              var prTitleAndDesc = getTitleAndDescription(sourceRef[1],
                                                          commitElements, 5);

              var title = prTitleAndDesc[0];
              var proposedDescription = prTitleAndDesc[1];

              var useGeneratedTitle = (
                   $('#pullrequest_title').hasClass('autogenerated-title') ||
                   $('#pullrequest_title').val() === "");

              if (title && useGeneratedTitle) {
                  // use generated title if we haven't specified our own
                  $('#pullrequest_title').val(title);
                  $('#pullrequest_title').addClass('autogenerated-title');

              }

              var useGeneratedDescription = (
                  !codeMirrorInstance._userDefinedDesc ||
                   codeMirrorInstance.getValue() === "");

              if (proposedDescription && useGeneratedDescription) {
                  // set proposed content, if we haven't defined our own,
                  // or we don't have description written
                  codeMirrorInstance._userDefinedDesc = false; // reset state
                  codeMirrorInstance.setValue(proposedDescription);
              }

              var msg = '';
              if (commitElements.length === 1) {
                  msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 1)}";
              } else {
                  msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 2)}";
              }

              msg += ' <a id="pull_request_overview_url" href="{0}" target="_blank">${_('Show detailed compare.')}</a>'.format(url);

              if (commitElements.length) {
                  var commitsLink = '<a href="#pull_request_overview"><strong>{0}</strong></a>'.format(commitElements.length);
                  prButtonLock(false, msg.replace('__COMMITS__', commitsLink), 'compare');
              }
              else {
                  prButtonLock(true, "${_('There are no commits to merge.')}", 'compare');
              }


          });
  };

  /**
   Generate Title and Description for a PullRequest.
   In case of 1 commits, the title and description is that one commit
   in case of multiple commits, we iterate on them with max N number of commits,
   and build description in a form
   - commitN
   - commitN+1
   ...

   Title is then constructed from branch names, or other references,
   replacing '-' and '_' into spaces

   * @param sourceRef
   * @param elements
   * @param limit
   * @returns {*[]}
   */
  var getTitleAndDescription = function(sourceRef, elements, limit) {
      var title = '';
      var desc = '';

      $.each($(elements).get().reverse().slice(0, limit), function(idx, value) {
          var rawMessage = $(value).find('td.td-description .message').data('messageRaw');
          desc += '- ' + rawMessage.split('\n')[0].replace(/\n+$/, "") + '\n';
      });
      // only 1 commit, use commit message as title
      if (elements.length == 1) {
          title = $(elements[0]).find('td.td-description .message').data('messageRaw').split('\n')[0];
      }
      else {
          // use reference name
          title = sourceRef.replace(/-/g, ' ').replace(/_/g, ' ').capitalizeFirstLetter();
      }

      return [title, desc]
  };

  var Select2Box = function(element, overrides) {
    var globalDefaults = {
        dropdownAutoWidth: true,
        containerCssClass: "drop-menu",
        dropdownCssClass: "drop-menu-dropdown"
    };

    var initSelect2 = function(defaultOptions) {
      var options = jQuery.extend(globalDefaults, defaultOptions, overrides);
      element.select2(options);
    };

    return {
      initRef: function() {
        var defaultOptions = {
          minimumResultsForSearch: 5,
          formatSelection: formatRefSelection
        };

        initSelect2(defaultOptions);
      },

      initRepo: function(defaultValue, readOnly) {
        var defaultOptions = {
          initSelection : function (element, callback) {
            var data = {id: defaultValue, text: defaultValue};
            callback(data);
          }
        };

        initSelect2(defaultOptions);

        element.select2('val', defaultSourceRepo);
        if (readOnly === true) {
          element.select2('readonly', true);
        }
      }
    };
  };

  var initTargetRefs = function(refsData, selectedRef){
    Select2Box($targetRef, {
      query: function(query) {
        queryTargetRefs(refsData, query);
      },
      initSelection : initRefSelection(selectedRef)
    }).initRef();

    if (!(selectedRef === undefined)) {
        $targetRef.select2('val', selectedRef);
    }
  };

  var targetRepoChanged = function(repoData) {
      // generate new DESC of target repo displayed next to select
      $('#target_repo_desc').html(
          "<strong>${_('Destination repository')}</strong>: {0}".format(repoData['description'])
      );

      // generate dynamic select2 for refs.
      initTargetRefs(repoData['refs']['select2_refs'],
                     repoData['refs']['selected_ref']);

  };

  var sourceRefSelect2 = Select2Box(
    $sourceRef, {
      placeholder: "${_('Select commit reference')}",
      query: function(query) {
        var initialData = defaultSourceRepoData['refs']['select2_refs'];
        queryTargetRefs(initialData, query)
      },
      initSelection: initRefSelection()
    }
  );

  var sourceRepoSelect2 = Select2Box($sourceRepo, {
    query: function(query) {}
  });

  var targetRepoSelect2 = Select2Box($targetRepo, {
    cachedDataSource: {},
    query: $.debounce(250, function(query) {
      queryTargetRepo(this, query);
    }),
    formatResult: formatResult
  });

  sourceRefSelect2.initRef();

  sourceRepoSelect2.initRepo(defaultSourceRepo, true);

  targetRepoSelect2.initRepo(defaultTargetRepo, false);

  $sourceRef.on('change', function(e){
    loadRepoRefDiffPreview();
    loadDefaultReviewers();
  });

  $targetRef.on('change', function(e){
    loadRepoRefDiffPreview();
    loadDefaultReviewers();
  });

  $targetRepo.on('change', function(e){
      var repoName = $(this).val();
      calculateContainerWidth();
      $targetRef.select2('destroy');
      $('#target_ref_loading').show();

      $.ajax({
          url: pyroutes.url('pullrequest_repo_refs',
            {'repo_name': targetRepoName, 'target_repo_name':repoName}),
          data: {},
          dataType: 'json',
          type: 'GET',
          success: function(data) {
              $('#target_ref_loading').hide();
              targetRepoChanged(data);
              loadRepoRefDiffPreview();
          },
          error: function(data, textStatus, errorThrown) {
              alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
          }
      })

  });

  var loadDefaultReviewers = function() {
    if (loadDefaultReviewers._currentRequest) {
        loadDefaultReviewers._currentRequest.abort();
    }
    $('.calculate-reviewers').show();
    prButtonLock(true, null, 'reviewers');

    var url = pyroutes.url('repo_default_reviewers_data', {'repo_name': targetRepoName});

    var sourceRepo = $sourceRepo.eq(0).val();
    var sourceRef = $sourceRef.eq(0).val().split(':');
    var targetRepo = $targetRepo.eq(0).val();
    var targetRef = $targetRef.eq(0).val().split(':');
    url += '?source_repo=' + sourceRepo;
    url += '&source_ref=' + sourceRef[2];
    url += '&target_repo=' + targetRepo;
    url += '&target_ref=' + targetRef[2];

    loadDefaultReviewers._currentRequest = $.get(url)
        .done(function(data) {
            loadDefaultReviewers._currentRequest = null;

            // reset && add the reviewer based on selected repo
            $('#review_members').html('');
            for (var i = 0; i < data.reviewers.length; i++) {
              var reviewer = data.reviewers[i];
              addReviewMember(
                  reviewer.user_id, reviewer.firstname,
                  reviewer.lastname, reviewer.username,
                  reviewer.gravatar_link, reviewer.reasons);
            }
            $('.calculate-reviewers').hide();
            prButtonLock(false, null, 'reviewers');
        });
  };

  prButtonLock(true, "${_('Please select origin and destination')}", 'all');

  // auto-load on init, the target refs select2
  calculateContainerWidth();
  targetRepoChanged(defaultTargetRepoData);

  $('#pullrequest_title').on('keyup', function(e){
      $(this).removeClass('autogenerated-title');
  });

  % if c.default_source_ref:
      // in case we have a pre-selected value, use it now
      $sourceRef.select2('val', '${c.default_source_ref}');
      loadRepoRefDiffPreview();
      loadDefaultReviewers();
  % endif

  ReviewerAutoComplete('#user');
});
</script>

</%def>