<!DOCTYPE html>
<html>
 <head>
    <title>Pervane - Plain text based note taking app</title> 

    <link rel="apple-touch-icon" sizes="180x180" href="static/img/favicon/apple-touch-icon.png">
    <link rel="icon" type="image/png" sizes="32x32" href="static/img/favicon/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="static/img/favicon/favicon-16x16.png">

    <link href="/static/css/bootstrap.min.css" rel="stylesheet" >
    <link href="/static/css/dropzone.min.css" rel="stylesheet" >
    <link href="https://fonts.googleapis.com/css?family=PT+Sans&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="/static/css/editormd.min.css" />
    <link rel="stylesheet" href="/static/css/styles.css" />
    <style>
    </style>
 </head>
 <body>

<header>
  <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark nav-narrow">
    <a class="navbar-brand" href="#">Pervane</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarCollapse">
      <ul class="navbar-nav mr-auto">
        <li class="nav-item active">
          <a class="nav-link" href="/">Home <span class="sr-only">(current)</span></a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#" data-toggle="modal" onclick="showSettingsModal()">Settings</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="https://reddit.com/r/pervane">Discuss/Feedback</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="https://github.com/hakanu/pervane">Contribute</a>
        </li>
      </ul>

			<button class="btn btn-large fileinput-button">Upload file</button>

      <form class="form-inline mt-2 mt-md-0" action="/search" method="GET">
        <input class="form-control mr-sm-2" type="text" name="query" placeholder="Search everything with ag or ack" aria-label="Search">
      </form>
    </div>
  </nav>
</header>

<div class="">
  <div class="row">
    <div class="col-sm-2 sidebar">
      <p>
        <a href="/">
          <i class="fa fa-folder" aria-hidden="true"></i>
          {{ tree.path|replace(working_dir, '')}}
        </a>

        <span>
          <a href="#" onclick="addNode('{{ tree.path.replace(working_dir, '') }}')">
            <i class="fa fa-plus-square" aria-hidden="true"></i>
          </a>
        </span>
      </p>

			<div class="input-group">
				<input class="search form-control" id="search-field" placeholder="Quick search" />
			</div>
			<div id="list-sidebar">
				<ul class="list">
				</ul>
			</div>

			<hr>

			<div>
        <ul>
				{%- for item in tree.children|sort(attribute='path') recursive %}
          {% set item_path = item.path.replace(working_dir, '') %}
					<li>
					{% if item.kind == 'file'  %}
						<a href="/file?f={{ item_path }}" id="{{item_path}}" data-path="{{item_path}}" class="path" draggable="true" ondragstart="drag(event)">
							{% if item.ext in note_extensions %}
								<i class="fa fa-file-text" aria-hidden="true"></i>
							{% else %}
								<i class="fa fa-file-code-o" aria-hidden="true"></i>
							{% endif %}
							{{ item.name }}
						</a>
					{% else %}
						<a href="#" data-href="/dir?d={{ item_path }}" id="{{item_path}}" data-path="{{item_path}}" class="expand path" draggable="false" ondrop="drop(event)" ondragover="allowDrop(event)">
							<i class="fa fa-folder" aria-hidden="true"></i>
							{{ item.name }}/
						</a>

						&nbsp;&nbsp;
						<span>
							<a href="#" onclick="addNode('{{ item_path }}')">
								<i class="fa fa-plus-square" aria-hidden="true"></i>
							</a>
						</span>
					{% endif %}

					{%- if item.children -%}
						<ul id="{{item_path|replace('.', '_')|replace(' ', '_')|replace('/', '-'|replace('\\', '-'))}}">{{ loop(item.children|sort(attribute='path')) }}</ul>
					{%- endif %}
					</li>
				{%- endfor %}
				</ul>
      </div>
      <p>Logged in as {{ current_user.username }}</p>
      <p><a href="/user/sign-out">Sign out</a></p>
    </div> <!-- /col-sm-2 -->

    <div class="col-sm-10">
      <p id="message"></p>
      {% if not search_results %}
        <h6>
          <a id="a-path" href="file://{{path}}" target="_blank">{{ path|replace(working_dir, '') }} </a>&nbsp;&nbsp;
          <span><a href="#" onclick="update()"><i class="fa fa-floppy-o" aria-hidden="true"></i>&nbsp;&nbsp;Save</a></span>
          <sub id="status"></sub>
        </h6>

        {% if mime_type.startswith('text/') %}
          {% if not md_content and html_content %}
            <div>{{ html_content|safe }}</div>
          {% else %}
            <div id="editor">
              <!-- Tips: Editor.md can auto append a `<textarea>` tag -->
              <textarea style="display:none;">### Hello Pervane!</textarea>
            </div>
          {% endif %}
        {% elif mime_type and mime_type.startswith('image/') %}
          <div>
            <img src="data:image/png;base64,{{ html_content }}" class="img-fluid" alt="{{ path }}"> 
      	  </div>
        {% else %}
          <pre><code class="{{ext|replace('.', '')}}">{{ html_content|e }}</code></pre>
        {% endif %}
        <p>{{ mime_type }}</p>
      {% else %}
        <h6>Results for <b>{{ query|e }}</b></h6>
        <p><sub>{{ stats }}</sub></p>
        {% for result in search_results %}
          <a href="/file?f={{ result.file}}" target="_blank">{{ result.file }}</a>
          <ul>
            {% for match in result.matches %}
              <li><pre>{{match.snippet}}</pre></li>
            {% endfor %}
          </ul>
        {% endfor %}
      {% endif %}
    </div>
  </div>
</div>

<br>
<br>

<!-- New folder/file Modal -->
<div class="modal fade" id="nodeModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLongTitle">Create new node</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <form id="form-add-node">
        <div class="modal-body">
          <p>Put / at the end if you want to create a directory. Otherwise we append a .md suffix for you.</p>
          <div class="input-group mb-3">
            <input id="modal-input-parent-path" type="hidden" name="parent_path" class="form-control"> 
            <div class="input-group-prepend">
              <span id="modal-input-prefix" class="input-group-text"></span>
            </div>
            <input id="modal-input-new-node-name" type="text" name="new_node_name" class="form-control" placeholder="Type new node's name">
          </div>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
          <button type="submit" class="btn btn-primary">Add node</button>
        </div>
      </form>
    </div>
  </div>
</div>

<!-- Settings Modal -->
<div class="modal fade" id="settings-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">Settings</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <header>
          <h6>Enabled Features</h6>
          <div class="form-check">
            <input class="form-check-input" type="checkbox" value="" id="settings-katex">
            <label class="form-check-label" for="settings-katex">TEX / KaTEX</label>
            <br>

            <input class="form-check-input" type="checkbox" value="" id="settings-charts">
            <label class="form-check-label" for="settings-charts">Charts</label>
            <br>

            <input class="form-check-input" type="checkbox" value="" id="settings-task-lists">
            <label class="form-check-label" for="settings-task-lists">Task Lists</label>
            <br>

            <input class="form-check-input" type="checkbox" value="" id="settings-sequences">
            <label class="form-check-label" for="settings-sequences">Sequence diagrams</label>
            <br>

            <input class="form-check-input" type="checkbox" value="" id="settings-code-folding">
            <label class="form-check-label" for="settings-code-folding">Code folding</label>
            <br>

            <input class="form-check-input" type="checkbox" value="" id="settings-emoji">
            <label class="form-check-label" for="settings-emoji">Emoji rendering</label>
            <br>

            <input class="form-check-input" type="checkbox" value="" id="settings-toolbar">
            <label class="form-check-label" for="settings-toolbar">Show WYSIWYG toolbar?</label>
            <br>
            <br>
          </div>

          <h6>Themes</h6>
          <div class="form-group">
            <select class="form-control" id="editormd-theme-select">
              <option selected="selected" value="">General theme</option>
            </select><br>
            <select class="form-control" id="editor-area-theme-select">
              <option selected="selected" value="">Editor area theme</option>
            </select><br>
            <select class="form-control" id="preview-area-theme-select">
              <option selected="selected" value="">Preview area theme</option>
            </select><br>
          </div>
        </header>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>

<script src="/static/js/jquery-3.4.1.min.js"></script>
<script src="/static/js/bootstrap.bundle.min.js"></script>
<script src="/static/js/dropzone.min.js"></script>
<script src="/static/js/editormd.min.js"></script>
<script src="/static/js/en.js"></script>
<script>
function fuzzy(source, s) {
    var hay = source.toLowerCase(), i = 0, n = -1, l;
    s = s.toLowerCase();
    for (; l = s[i++] ;) if (!~(n = hay.indexOf(l, n + 1))) return false;
    return true;
};

// Get expand/collapse memory from localstorage.
for (var i = 0; i < localStorage.length; i++) {
  var key = localStorage.key(i);
  var value = localStorage.getItem(key);
  // Hacky but useful way to generate ids from folder paths.
  // needed to use false as a str because is(visible) is serialized :/
  if (value != 'false') {
    $('#' + key).eq(0).css("display", "block");
  }
}

function showSettingsModal() {
  // Show the modal upon click.
  $('#settings-modal').modal();

  // Init settings.
  // Modal should be initialized for these.
  if (localStorage.settingsKatex)  {
    $('#settings-katex')[0].checked = localStorage.settingsKatex == '1';
  }

  if (localStorage.settingsTaskLists)  {
    $('#settings-task-lists')[0].checked = localStorage.settingsTaskLists == '1';
  }

  if (localStorage.settingsCharts)  {
    $('#settings-charts')[0].checked = localStorage.settingsCharts == '1';
  }

  if (localStorage.settingsSequences) {
    $('#settings-sequences')[0].checked = localStorage.settingsSequences == '1';
  }

  if (localStorage.settingsCodeFolding) {
    $('#settings-code-folding')[0].checked = localStorage.settingsCodeFolding == '1';
  }

  if (localStorage.settingsEmoji) {
    $('#settings-emoji')[0].checked = localStorage.settingsEmoji == '1';
  }

  if (localStorage.settingsToolbar) {
    $('#settings-toolbar')[0].checked = localStorage.settingsToolbar == '1';
  }
}

$('.expand').click(function() {
  var nearest_ul = $('ul', $(this).parent()).eq(0);
  nearest_ul.toggle();
  window.localStorage.setItem(nearest_ul.attr('id'),
                              nearest_ul.is(':visible'));
});

{% if (md_content or md != '') and path and not mime_type.startswith('image/') %}
  console.log('initing the editor');
  initEditor('{{path}}');
{% else %}
  console.log('no need to init the editor');
{% endif %}

var editor = null;

function initEditor(path) {
  if (path) {
    $.get( 
      "/api/get_content", { 
        f: path 
      }, 
      function(data) { 
        if (data.result == 'success') {
          // TODO(hakanu): No idea why this is not working.
          // editor.setValue(data.content);
          // editor.setMarkdown(data.content);
          editor = editormd("editor", {
              width: "100%",
              height: "150%",
              taskList: (localStorage.settingsTaskLists) ? (localStorage.settingsTaskLists == '1'): false,
              // autoHeight: true,
              codeFold: (localStorage.settingsCodeFolding) ? (localStorage.settingsCodeFolding == '1'): false,
              searchReplace: true,
              flowChart: (localStorage.settingsCharts) ? (localStorage.settingsCharts == '1'): false,
              sequenceDiagram: (localStorage.settingsSequences) ? (localStorage.settingsSequences == '1'): false,
              tex: (localStorage.settingsKatex) ? (localStorage.settingsKatex == '1'): false,
              emoji: (localStorage.settingsEmoji) ? (localStorage.settingsEmoji == '1'): false,
              toolbar: (localStorage.settingsToolbar) ? (localStorage.settingsToolbar == '1'): true,
              theme: (localStorage.theme) ? localStorage.theme : "dark",
              previewTheme: (localStorage.previewTheme) ? localStorage.previewTheme : "dark", 
              editorTheme: (localStorage.editorTheme) ? localStorage.editorTheme : "pastel-on-dark", 
              // TODO(hakanu): Needed to load like this. Otherwise editor
              // puts its own placeholder to the textarea instead of empty.
              markdown: data.content + '\n',  
              path : "/static/js/lib/",  // Autoload modules mode.
              onload : function() {
                  console.log('onload', this);
                  // Make the preview pane non-default.
                  this.unwatch();
              }
          });
        } else {
          console.log('something went wrong while fetching the file content', data.result);
          $('#status').text('something went wrong while fetching the file content', data.result);
        }
      }); 
  }
}

function update() {
  var text = editor.getMarkdown();
  var file_path = $('#a-path').text();

  $.post(
    '/api/update', {
        updated_content: text,
        file_path: file_path
    }, function(result){
      if (result.result == 'success') {
        $('#status').text('Updated @ ' + (new Date()));
      } else {
        $('#status').text('Failed to update @ ' + (new Date()));
      }
  });
}

function addNode(parent) {
  $('#modal-input-parent-path').attr('value', parent);
  $('#modal-input-prefix').text(parent + '/');
  $('#nodeModal').modal();
}

function themeSelect(id, themes, lsKey, callback) {
  var select = $("#" + id);
  for (var i = 0, len = themes.length; i < len; i ++) {                    
      var theme    = themes[i];
      var selected = (localStorage[lsKey] == theme) ? " selected=\"selected\"" : "";
      select.append("<option value=\"" + theme + "\"" + selected + ">" + theme + "</option>");
  }
  
  select.bind("change", function(){
      var theme = $(this).val();
      if (theme === "") {
          alert("theme == \"\"");
          return false;
      }
      localStorage[lsKey] = theme;
      callback(select, theme);
  }); 
  return select;
}

themeSelect("editormd-theme-select", editormd.themes, "theme", function($this, theme) {
    editor.setTheme(theme);
});

themeSelect("editor-area-theme-select", editormd.editorThemes, "editorTheme", function($this, theme) {
    editor.setCodeMirrorTheme(theme); 
});

themeSelect("preview-area-theme-select", editormd.previewThemes, "previewTheme", function($this, theme) {
    editor.setPreviewTheme(theme);
}); 

$('#settings-katex').change(function() {
   if (this.checked) {
     localStorage.setItem('settingsKatex', 1);
   } else {
     localStorage.setItem('settingsKatex', 0);
   }
});

$('#settings-charts').change(function() {
   if (this.checked) {
     localStorage.setItem('settingsCharts', 1);
   } else {
     localStorage.setItem('settingsCharts', 0);
   }
});

$('#settings-task-lists').change(function() {
   if (this.checked) {
     localStorage.setItem('settingsTaskLists', 1);
   } else {
     localStorage.setItem('settingsTaskLists', 0);
   }
});

$('#settings-sequences').change(function() {
   if (this.checked) {
     localStorage.setItem('settingsSequences', 1);
   } else {
     localStorage.setItem('settingsSequences', 0);
   }
});

$('#settings-code-folding').change(function() {
   if (this.checked) {
     localStorage.setItem('settingsCodeFolding', 1);
   } else {
     localStorage.setItem('settingsCodeFolding', 0);
   }
});

$('#settings-emoji').change(function() {
   if (this.checked) {
     localStorage.setItem('settingsEmoji', 1);
   } else {
     localStorage.setItem('settingsEmoji', 0);
   }
});

$('#settings-toolbar').change(function() {
   if (this.checked) {
     localStorage.setItem('settingsToolbar', 1);
   } else {
     localStorage.setItem('settingsToolbar', 0);
   }
});

Dropzone.autoDiscover = false;

$(function() {
  var myDropzone = new Dropzone(document.body, {
		clickable: '.fileinput-button',
    url: '/upload',
		acceptedFiles: 'image/*,application/pdf',
		maxFilesize: 2,  // MB
	});

  myDropzone.on('addedfile', function(file) {
		console.log('File added');
  });

  myDropzone.on('success', function(file, response) {
    if (response.result == 'success') {
      window.location.replace('/file?f=' + response.entity);
    } else {
      $('#message').text('Fail:/ ' + response.message);
      myDropzone.removeFile(file);
    }
  });
});

// Fuzzy search.
var values = [];
{% if file_paths_flat %}
  values = {{ file_paths_flat|safe }};
{%endif %}

$('#list-sidebar').hide();
$('#search-field').on('keyup', function() {
  var searchString = $(this).val();
  if (searchString == '') {
		$('#list-sidebar').hide();
  } else {
		$('#list-sidebar').children().remove();
    for (var i = 0; i < values.length; i++) {
			var path = values[i].path;
			if (fuzzy(path, searchString)) {
				$('#list-sidebar').append('<li><a href="/file?f=' + path +'">' + values[i].name +'</a></li>');
			}
		}
		$('#list-sidebar').show();
	}
});

// Ctrl + s saving.
$(document).keydown(function(event) {
    // 19 for Mac Command+S
    if (!( String.fromCharCode(event.which).toLowerCase() == 's' && event.ctrlKey) && !(event.which == 19)) return true;
    event.preventDefault();
    update();
    return false;
});

$(document).keydown(function(event) {
    // 19 for Mac Command+S
    if (!( String.fromCharCode(event.which).toLowerCase() == 'p' && event.ctrlKey) && !(event.which == 19)) return true;
    event.preventDefault();
    $('#search-field').focus();
    return false;
});

// Drag drop file move
function allowDrop(ev) {
  ev.preventDefault();
}

function drag(ev) {
  ev.dataTransfer.setData('source_path', ev.target.id);
}

function drop(ev) {
  ev.preventDefault();
  var source_path  = ev.dataTransfer.getData('source_path');
	var dest_dir = ev.target.id;

  $.get(
    '/api/move_file', {
        source_path: source_path,
        dest_dir: dest_dir, 
    }, function(result){
      if (result.result == 'success') {
				console.log('Moved the file, refreshing');
        window.location.replace('/');
      } else {
				console.log('Failed to move the file');
      }
  });
}

// File/directory creation form handling.
$('#form-add-node').submit(function(event) {
  event.preventDefault();
  console.log('adding node');
  var  parentPath = $('#modal-input-parent-path').val();
  var newNodeName = $('#modal-input-new-node-name').val();
  $.post(
    '/api/add_node', {
        parent_path: parentPath,
        new_node_name: newNodeName,
    }, function(result){
      if (result.result == 'success') {
        console.log('Created file, refreshing');
        var dest = '/';
        if (!result.entity.endsWith('/')) {
          dest = '/file?f=' + result.entity;
        }
        window.location.replace(dest);
      } else {
        console.log('Failed to create the file or dir');
        $('#message').text(result.message);
      }
  });
});

</script>
</body>
</html>

