/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-â
âvi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :viâ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¡
â Copyright 2020 Justine Alexandra Roberts Tunney                              â
â                                                                              â
â Permission to use, copy, modify, and/or distribute this software for         â
â any purpose with or without fee is hereby granted, provided that the         â
â above copyright notice and this permission notice appear in all copies.      â
â                                                                              â
â THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                â
â WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                â
â WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             â
â AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         â
â DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        â
â PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               â
â TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             â
â PERFORMANCE OF THIS SOFTWARE.                                                â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/stat.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/log/check.h"
#include "libc/mem/alg.h"
#include "libc/mem/gc.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/dt.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/x/x.h"

/**
 * @fileoverview Pretty fast substring refactor tool.
 */

static const char kBefore[] = "\
â Copyright 2020 Justine Alexandra Roberts Tunney                              â\n\
â                                                                              â\n\
â This program is free software; you can redistribute it and/or modify         â\n\
â it under the terms of the GNU General Public License as published by         â\n\
â the Free Software Foundation; version 2 of the License.                      â\n\
â                                                                              â\n\
â This program is distributed in the hope that it will be useful, but          â\n\
â WITHOUT ANY WARRANTY; without even the implied warranty of                   â\n\
â MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU             â\n\
â General Public License for more details.                                     â\n\
â                                                                              â\n\
â You should have received a copy of the GNU General Public License            â\n\
â along with this program; if not, write to the Free Software                  â\n\
â Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA                â\n\
â 02110-1301 USA                                                               â\n\
";
const char kAfter[] = "\
â Copyright 2020 Justine Alexandra Roberts Tunney                              â\n\
â                                                                              â\n\
â Permission to use, copy, modify, and/or distribute this software for         â\n\
â any purpose with or without fee is hereby granted, provided that the         â\n\
â above copyright notice and this permission notice appear in all copies.      â\n\
â                                                                              â\n\
â THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                â\n\
â WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                â\n\
â WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             â\n\
â AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         â\n\
â DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        â\n\
â PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               â\n\
â TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             â\n\
â PERFORMANCE OF THIS SOFTWARE.                                                â\n\
";

#if 0
static const char kBefore[] = "\
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-â";
const char kAfter[] = "\
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-â";
#endif

void RefactorFile(const char *path) {
  int fd;
  struct stat st;
  size_t len, partlen, len1, len2;
  char *mem, *spot = NULL, *part1, *part2;
  CHECK_NE(-1, (fd = open(path, O_RDONLY)));
  CHECK_NE(-1, fstat(fd, &st));
  len2 = 0;
  if ((len = st.st_size)) {
    CHECK_NE(MAP_FAILED,
             (mem = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0)));
    partlen = sizeof(kBefore) - 1;
    if ((spot = memmem(mem, len, kBefore, partlen))) {
      part1 = gc(xmalloc((len1 = spot - mem)));
      part2 = gc(xmalloc((len2 = len - partlen - (spot - mem))));
      memcpy(part1, mem, len1);
      memcpy(part2, spot + partlen, len2);
    }
    CHECK_NE(-1, munmap(mem, len));
  }
  CHECK_NE(-1, close(fd));
  if (spot) {
    fprintf(stderr, "found! %s\n", path);
    CHECK_NE(-1, (fd = open(path, O_RDWR | O_TRUNC)));
    CHECK_EQ(len1, write(fd, part1, len1));
    CHECK_EQ(sizeof(kAfter) - 1, write(fd, kAfter, sizeof(kAfter) - 1));
    CHECK_EQ(len2, write(fd, part2, len2));
    CHECK_NE(-1, close(fd));
  }
}

void RefactorDir(const char *dpath) {
  DIR *dir;
  struct dirent *ent;
  char *path = gc(xmalloc(4096));
  CHECK_NOTNULL(dir = opendir(firstnonnull(dpath, ".")));
  while ((ent = readdir(dir))) {
    if (_startswith(ent->d_name, ".")) continue;
    if (strcmp(ent->d_name, "o") == 0) continue;
    snprintf(path, 4096, "%s%s%s", dpath ? dpath : "", dpath ? "/" : "",
             ent->d_name);
    if (isdirectory(path)) {
      RefactorDir(path);
    } else if (isregularfile(path)) {
      RefactorFile(path);
    }
  }
  CHECK_NE(-1, closedir(dir));
}

int main(int argc, char *argv[]) {
  RefactorDir(NULL);
  return 0;
}
